OSDN Git Service

[gcc/ChangeLog]
[pf3gnuchains/gcc-fork.git] / gcc / objc / objc-act.c
index 24fcffe..aefb4fb 100644 (file)
@@ -1,6 +1,6 @@
 /* Implement classes and message passing for Objective C.
    Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Steve Naroff.
 
 This file is part of GCC.
@@ -50,6 +50,7 @@ Boston, MA 02111-1307, USA.  */
 #include "c-tree.h"
 #include "c-common.h"
 #include "flags.h"
+#include "langhooks.h"
 #include "objc-act.h"
 #include "input.h"
 #include "except.h"
@@ -62,8 +63,8 @@ Boston, MA 02111-1307, USA.  */
 #include "target.h"
 #include "diagnostic.h"
 #include "cgraph.h"
-
-#define OBJC_VOID_AT_END       build_tree_list (NULL_TREE, void_type_node)
+#include "tree-iterator.h"
+#include "libfuncs.h"
 
 /* This is the default way of generating a method name.  */
 /* I am not sure it is really correct.
@@ -131,17 +132,11 @@ static tree build_objc_method_call (int, tree, tree, tree, tree);
 static void generate_strings (void);
 static tree get_proto_encoding (tree);
 static void build_selector_translation_table (void);
-
+static tree lookup_interface (tree);
 static tree objc_add_static_instance (tree, tree);
 
 static void build_objc_exception_stuff (void);
-static tree objc_declare_variable (enum rid, tree, tree, tree);
-static tree objc_enter_block (void);
-static tree objc_exit_block (void);
-static void objc_build_try_enter_fragment (void);
-static void objc_build_try_exit_fragment (void);
-static void objc_build_extract_fragment (void);
-static tree objc_build_extract_expr (void);
+static void build_next_objc_exception_stuff (void);
 
 static tree build_ivar_template (void);
 static tree build_method_template (void);
@@ -149,7 +144,7 @@ static tree build_private_template (tree);
 static void build_class_template (void);
 static void build_selector_template (void);
 static void build_category_template (void);
-static tree lookup_method_in_hash_lists (tree);
+static tree lookup_method_in_hash_lists (tree, int);
 static void build_super_template (void);
 static tree build_category_initializer (tree, tree, tree, tree, tree, tree);
 static tree build_protocol_initializer (tree, tree, tree, tree, tree);
@@ -160,7 +155,6 @@ static void generate_ivar_lists (void);
 static void generate_dispatch_tables (void);
 static void generate_shared_structures (void);
 static tree generate_protocol_list (tree);
-static void generate_forward_declaration_to_string_table (void);
 static void build_protocol_reference (tree);
 
 static tree build_keyword_selector (tree);
@@ -184,8 +178,10 @@ static hash hash_lookup (hash *, tree);
 static void hash_add_attr (hash, tree);
 static tree lookup_method (tree, tree);
 static tree lookup_method_static (tree, tree, int);
+static void add_method_to_hash_list (hash *, tree);
 static tree add_class (tree);
 static void add_category (tree, tree);
+static inline tree lookup_category (tree, tree);
 
 enum string_section
 {
@@ -280,7 +276,7 @@ static tree build_shared_structure_initializer (tree, tree, tree, tree,
 static void generate_category (tree);
 static int is_objc_type_qualifier (tree);
 static tree adjust_type_for_id_default (tree);
-static tree check_duplicates (hash, int);
+static tree check_duplicates (hash, int, int);
 static tree receiver_is_class_object (tree, int, int);
 static int check_methods (tree, tree, int);
 static int conforms_to_protocol (tree, tree);
@@ -365,23 +361,6 @@ static const char *default_constant_string_class_name;
 #define TAG_RETURN_STRUCT              "objc_return_struct"
 
 #define UTAG_EXCDATA                   "_objc_exception_data"
-#define UTAG_EXCDATA_VAR               "_stackExceptionData"
-#define UTAG_CAUGHTEXC_VAR             "_caughtException"
-#define UTAG_RETHROWEXC_VAR            "_rethrowException"
-#define UTAG_EVALONCE_VAR              "_eval_once"
-
-struct val_stack {
-  long val;
-  struct val_stack *next;
-};
-static struct val_stack *catch_count_stack, *exc_binding_stack;
-
-/* useful for debugging */
-static int if_nesting_count;
-static int blk_nesting_count;
-
-static void val_stack_push (struct val_stack **, long);
-static void val_stack_pop (struct val_stack **);
 
 /* The OCTI_... enumeration itself is in objc/objc-act.h.  */
 tree objc_global_trees[OCTI_MAX];
@@ -537,10 +516,9 @@ objc_init (void)
 }
 
 void
-finish_file (void)
+objc_finish_file (void)
 {
   mark_referenced_methods ();
-  c_objc_common_finish_file ();
 
   /* Finalize Objective-C runtime data.  No need to generate tables
      and code if only checking syntax.  */
@@ -559,9 +537,13 @@ define_decl (tree declarator, tree declspecs)
   return decl;
 }
 
+/* Return the first occurrence of a method declaration corresponding
+   to sel_name in rproto_list.  Search rproto_list recursively.
+   If is_class is 0, search for instance methods, otherwise for class
+   methods.  */
 static tree
 lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
-                               int class_meth)
+                               int is_class)
 {
    tree rproto, p;
    tree fnd = 0;
@@ -572,13 +554,13 @@ lookup_method_in_protocol_list (tree rproto_list, tree sel_name,
 
        if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE)
          {
-           if ((fnd = lookup_method (class_meth
+           if ((fnd = lookup_method (is_class
                                      ? PROTOCOL_CLS_METHODS (p)
                                      : PROTOCOL_NST_METHODS (p), sel_name)))
              ;
            else if (PROTOCOL_LIST (p))
              fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p),
-                                                   sel_name, class_meth);
+                                                   sel_name, is_class);
          }
        else
           {
@@ -626,6 +608,37 @@ lookup_protocol_in_reflist (tree rproto_list, tree lproto)
   return 0;
 }
 
+/* Return 1 if IDENT is an ObjC/ObjC++ reserved keyword in the context of
+   an '@'.  */
+
+int
+objc_is_reserved_word (tree ident)
+{
+  unsigned char code = C_RID_CODE (ident);
+
+  return (OBJC_IS_AT_KEYWORD (code)
+#ifdef OBJCPLUS
+         || code == RID_CLASS || code == RID_PUBLIC
+         || code == RID_PROTECTED || code == RID_PRIVATE
+         || code == RID_TRY || code == RID_THROW || code == RID_CATCH
+#endif
+           );
+}
+
+/* Return true if TYPE is 'id'.  */
+
+static bool
+objc_is_object_id (tree type)
+{
+  return OBJC_TYPE_NAME (type) == objc_object_id;
+}
+
+static bool
+objc_is_class_id (tree type)
+{
+  return OBJC_TYPE_NAME (type) == objc_class_id;
+}
+
 /* 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
@@ -777,12 +790,12 @@ objc_comptypes (tree lhs, tree rhs, int reflexive)
              return 1;
            }
          /* <Protocol> = id */
-         else if (OBJC_TYPE_NAME (TREE_TYPE (rhs)) == objc_object_id)
+         else if (objc_is_object_id (TREE_TYPE (rhs)))
            {
              return 1;
            }
          /* <Protocol> = Class */
-         else if (OBJC_TYPE_NAME (TREE_TYPE (rhs)) == objc_class_id)
+         else if (objc_is_class_id (TREE_TYPE (rhs)))
            {
              return 0;
            }
@@ -854,12 +867,12 @@ objc_comptypes (tree lhs, tree rhs, int reflexive)
                return 0;
            }
          /* id = <Protocol> */
-         else if (OBJC_TYPE_NAME (TREE_TYPE (lhs)) == objc_object_id)
+         else if (objc_is_object_id (TREE_TYPE (lhs)))
            {
              return 1;
            }
          /* Class = <Protocol> */
-         else if (OBJC_TYPE_NAME (TREE_TYPE (lhs)) == objc_class_id)
+         else if (objc_is_class_id (TREE_TYPE (lhs)))
            {
              return 0;
            }
@@ -892,18 +905,21 @@ objc_comptypes (tree lhs, tree rhs, int reflexive)
      'Object *o = [[Object alloc] init]; falls
      in the case <class> * = `id'.
   */
-  if ((OBJC_TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
-      || (OBJC_TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
+  if ((objc_is_object_id (lhs) && TYPED_OBJECT (rhs))
+      || (objc_is_object_id (rhs) && TYPED_OBJECT (lhs)))
     return 1;
 
   /* `id' = `Class', `Class' = `id' */
 
-  else if ((OBJC_TYPE_NAME (lhs) == objc_object_id
-           && OBJC_TYPE_NAME (rhs) == objc_class_id)
-          || (OBJC_TYPE_NAME (lhs) == objc_class_id
-              && OBJC_TYPE_NAME (rhs) == objc_object_id))
+  else if ((objc_is_object_id (lhs) && objc_is_class_id (rhs))
+          || (objc_is_class_id (lhs) && objc_is_object_id (rhs)))
     return 1;
 
+  /* `Class' != `<class> *' && `<class> *' != `Class'!  */
+  else if ((OBJC_TYPE_NAME (lhs) == objc_class_id && TYPED_OBJECT (rhs))
+          || (OBJC_TYPE_NAME (rhs) == objc_class_id && TYPED_OBJECT (lhs)))
+    return 0;
+
   /* `<class> *' = `<class> *' */
 
   else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
@@ -945,10 +961,9 @@ objc_check_decl (tree decl)
 
   if (TREE_CODE (type) != RECORD_TYPE)
     return;
-  if (TYPE_NAME (type) && (type = is_class_name (TYPE_NAME (type)))
-      && type != constant_string_type)
+  if (OBJC_TYPE_NAME (type) && (type = objc_is_class_name (OBJC_TYPE_NAME (type))))
     error ("statically allocated instance of Objective-C class `%s'",
-            IDENTIFIER_POINTER (type));
+          IDENTIFIER_POINTER (type));
 }
 
 /* Implement static typing.  At this point, we know we have an interface.  */
@@ -960,32 +975,19 @@ get_static_reference (tree interface, tree protocols)
 
   if (protocols)
     {
-      tree t, m = TYPE_MAIN_VARIANT (type);
-
-      t = copy_node (type);
-
-      /* Add this type to the chain of variants of TYPE.  */
-      TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
-      TYPE_NEXT_VARIANT (m) = t;
-
+      type = build_variant_type_copy (type);
+      
       /* Look up protocols and install in lang specific list.  Note
         that the protocol list can have a different lifetime than T!  */
-      SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
-
-      /* This forces a new pointer type to be created later
-        (in build_pointer_type)...so that the new template
-        we just created will actually be used...what a hack!  */
-      if (TYPE_POINTER_TO (t))
-       TYPE_POINTER_TO (t) = NULL_TREE;
-
-      type = t;
+      SET_TYPE_PROTOCOL_LIST (type, lookup_and_install_protocols (protocols));
     }
 
   return type;
 }
 
+/* Return a declaration corresponding to a protocol list qualified 'id'. */
 tree
-get_object_reference (tree protocols)
+get_protocol_reference (tree protocols)
 {
   tree type_decl = lookup_name (objc_id_id);
   tree type;
@@ -993,7 +995,7 @@ get_object_reference (tree protocols)
   if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
     {
       type = TREE_TYPE (type_decl);
-      if (TYPE_MAIN_VARIANT (type) != id_type)
+      if (TYPE_MAIN_VARIANT (type) != objc_id_type)
        warning ("unexpected type for `id' (%s)",
                 gen_declaration (type, errbuf));
     }
@@ -1009,24 +1011,10 @@ get_object_reference (tree protocols)
 
   if (protocols)
     {
-      tree t, m = TYPE_MAIN_VARIANT (type);
-
-      t = copy_node (type);
-
-      /* Add this type to the chain of variants of TYPE.  */
-      TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
-      TYPE_NEXT_VARIANT (m) = t;
+      type = build_variant_type_copy (type);
 
       /* Look up protocols...and install in lang specific list */
-      SET_TYPE_PROTOCOL_LIST (t, lookup_and_install_protocols (protocols));
-
-      /* This forces a new pointer type to be created later
-        (in build_pointer_type)...so that the new template
-        we just created will actually be used...what a hack!  */
-      if (TYPE_POINTER_TO (t))
-       TYPE_POINTER_TO (t) = NULL_TREE;
-
-      type = t;
+      SET_TYPE_PROTOCOL_LIST (type, lookup_and_install_protocols (protocols));
     }
   return type;
 }
@@ -1092,7 +1080,7 @@ create_builtin_decl (enum tree_code code, tree type, const char *name)
   if (code == VAR_DECL)
     {
       TREE_STATIC (decl) = 1;
-      make_decl_rtl (decl, 0);
+      make_decl_rtl (decl);
       pushdecl (decl);
       DECL_ARTIFICIAL (decl) = 1;
     }
@@ -1144,7 +1132,7 @@ synth_module_prologue (void)
 
   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
 
-  id_type = build_pointer_type (objc_object_reference);
+  objc_id_type = build_pointer_type (objc_object_reference);
 
   objc_id_id = get_identifier (TYPE_ID);
   objc_class_id = get_identifier (TAG_CLASS);
@@ -1152,129 +1140,116 @@ synth_module_prologue (void)
   objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
   temp_type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
   objc_declare_class (tree_cons (NULL_TREE, temp_type, NULL_TREE));
-  protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
-                                temp_type));
+  objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE, temp_type));
 
   /* Declare type of selector-objects that represent an operation name.  */
 
-  /* `struct objc_selector *' */
-  selector_type
-    = build_pointer_type (xref_tag (RECORD_TYPE,
-                                   get_identifier (TAG_SELECTOR)));
+  if (flag_next_runtime)
+    /* `struct objc_selector *' */
+    objc_selector_type
+      = build_pointer_type (xref_tag (RECORD_TYPE,
+                                     get_identifier (TAG_SELECTOR)));
+  else
+    /* `const struct objc_selector *' */
+    objc_selector_type
+      = build_pointer_type
+       (build_qualified_type (xref_tag (RECORD_TYPE,
+                                        get_identifier (TAG_SELECTOR)),
+                              TYPE_QUAL_CONST));
 
-  /* Forward declare type, or else the prototype for msgSendSuper will
-     complain.  */
+  /* Declare receiver type used for dispatching messages to 'super'.  */
 
   /* `struct objc_super *' */
-  super_type = build_pointer_type (xref_tag (RECORD_TYPE,
-                                         get_identifier (TAG_SUPER)));
-
-
-  /* id objc_msgSend (id, SEL, ...); */
+  objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
+                                                 get_identifier (TAG_SUPER)));
 
-  temp_type
-    = build_function_type (id_type,
-                          tree_cons (NULL_TREE, id_type,
-                                     tree_cons (NULL_TREE, selector_type,
-                                                NULL_TREE)));
-
-  if (! flag_next_runtime)
+  if (flag_next_runtime)
     {
-      umsg_decl = build_decl (FUNCTION_DECL,
-                             get_identifier (TAG_MSGSEND), temp_type);
-      DECL_EXTERNAL (umsg_decl) = 1;
-      TREE_PUBLIC (umsg_decl) = 1;
-      DECL_INLINE (umsg_decl) = 1;
-      DECL_ARTIFICIAL (umsg_decl) = 1;
+      /* NB: In order to call one of the ..._stret (struct-returning)
+      functions, the function *MUST* first be cast to a signature that
+      corresponds to the actual ObjC method being invoked.  This is
+      what is done by the build_objc_method_call() routine below.  */
 
-      make_decl_rtl (umsg_decl, NULL);
-      pushdecl (umsg_decl);
-    }
-  else
-    {
+      /* id objc_msgSend (id, SEL, ...); */
+      /* id objc_msgSendNonNil (id, SEL, ...); */
+      /* id objc_msgSend_stret (id, SEL, ...); */
+      /* id objc_msgSendNonNil_stret (id, SEL, ...); */
+      temp_type
+       = build_function_type (objc_id_type,
+                              tree_cons (NULL_TREE, objc_id_type,
+                                         tree_cons (NULL_TREE, 
+                                                    objc_selector_type,
+                                                    NULL_TREE)));
       umsg_decl = builtin_function (TAG_MSGSEND,
                                    temp_type, 0, NOT_BUILT_IN,
                                    NULL, NULL_TREE);
-      /* id objc_msgSendNonNil (id, SEL, ...); */
       umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
                                           temp_type, 0, NOT_BUILT_IN,
                                           NULL, NULL_TREE);
-    }
-
-  /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
-
-  temp_type
-    = build_function_type (id_type,
-                          tree_cons (NULL_TREE, super_type,
-                                     tree_cons (NULL_TREE, selector_type,
-                                                NULL_TREE)));
-
-  umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
-                                     temp_type, 0, NOT_BUILT_IN,
-                                     NULL, NULL_TREE);
-
-  /* The NeXT runtime defines the following additional entry points,
-     used for dispatching calls to methods returning structs:
-
-     #if defined(__cplusplus)
-       id objc_msgSend_stret(id self, SEL op, ...);
-       id objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...);
-     #else
-       void objc_msgSend_stret(void * stretAddr, id self, SEL op, ...);
-       void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
-                                   SEL op, ...);
-     #endif
-
-     struct objc_return_struct objc_msgSendNonNil_stret(id self, SEL op, ...);
-
-     These prototypes appear in <objc/objc-runtime.h>; however, they
-     CANNOT BE USED DIRECTLY.  In order to call one of the ..._stret
-     functions, the function must first be cast to a signature that
-     corresponds to the actual ObjC method being invoked.  This is
-     what is done by the build_objc_method_call() routine below.  */
-
-  if (flag_next_runtime)
-    {
-      tree objc_return_struct_type
-       = xref_tag (RECORD_TYPE,
-                   get_identifier (TAG_RETURN_STRUCT));
-
-      tree stret_temp_type
-       = build_function_type (id_type,
-                              tree_cons (NULL_TREE, id_type,
-                                         tree_cons (NULL_TREE, selector_type,
-                                                    NULL_TREE)));
-
       umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
-                                         stret_temp_type, 0, NOT_BUILT_IN,
+                                         temp_type, 0, NOT_BUILT_IN,
                                          NULL, NULL_TREE);
-      stret_temp_type
-       = build_function_type (objc_return_struct_type,
-                              tree_cons (NULL_TREE, id_type,
-                                         tree_cons (NULL_TREE, selector_type,
-                                                    NULL_TREE)));
-
       umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
-                                                stret_temp_type, 0, NOT_BUILT_IN,
+                                                temp_type, 0, NOT_BUILT_IN,
                                                 NULL, NULL_TREE);
 
-      stret_temp_type
-       = build_function_type (id_type,
-                              tree_cons (NULL_TREE, super_type,
-                                         tree_cons (NULL_TREE, selector_type,
+      /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
+      /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
+      temp_type
+       = build_function_type (objc_id_type,
+                              tree_cons (NULL_TREE, objc_super_type,
+                                         tree_cons (NULL_TREE,
+                                                    objc_selector_type,
                                                     NULL_TREE)));
-
+      umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
+                                         temp_type, 0, NOT_BUILT_IN,
+                                         NULL, NULL_TREE);
       umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
-                                               stret_temp_type, 0, NOT_BUILT_IN, 0,
+                                               temp_type, 0, NOT_BUILT_IN, 0,
                                                NULL_TREE);
     }
+  else
+    {
+      /* GNU runtime messenger entry points.  */
+
+      /* typedef id (*IMP)(id, SEL, ...); */
+      tree IMP_type
+       = build_pointer_type
+         (build_function_type (objc_id_type,      
+                               tree_cons (NULL_TREE, objc_id_type,      
+                                          tree_cons (NULL_TREE,
+                                                     objc_selector_type,      
+                                                     NULL_TREE))));      
+
+      /* IMP objc_msg_lookup (id, SEL); */
+      temp_type
+        = build_function_type (IMP_type,
+                               tree_cons (NULL_TREE, objc_id_type,
+                                          tree_cons (NULL_TREE,
+                                                    objc_selector_type,
+                                                     void_list_node)));
+      umsg_decl = builtin_function (TAG_MSGSEND,
+                                   temp_type, 0, NOT_BUILT_IN,
+                                   NULL, NULL_TREE);
+
+      /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
+      temp_type
+        = build_function_type (IMP_type,
+                               tree_cons (NULL_TREE, objc_super_type,
+                                          tree_cons (NULL_TREE,
+                                                    objc_selector_type,
+                                                     void_list_node)));
+      umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
+                                         temp_type, 0, NOT_BUILT_IN,
+                                         NULL, NULL_TREE);
+    }
 
   /* id objc_getClass (const char *); */
 
-  temp_type = build_function_type (id_type,
+  temp_type = build_function_type (objc_id_type,
                                   tree_cons (NULL_TREE,
                                              const_string_type_node,
-                                             OBJC_VOID_AT_END));
+                                             void_list_node));
 
   objc_get_class_decl
     = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN,
@@ -1286,8 +1261,9 @@ synth_module_prologue (void)
     = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
 
   build_super_template ();
+  build_objc_exception_stuff ();
   if (flag_next_runtime)
-    build_objc_exception_stuff ();
+    build_next_objc_exception_stuff ();
 
   /* static SEL _OBJC_SELECTOR_TABLE[]; */
 
@@ -1309,7 +1285,7 @@ synth_module_prologue (void)
          debug_hooks = save_hooks;
        }
       else
-       temp_type = build_array_type (selector_type, NULL_TREE);
+       temp_type = build_array_type (objc_selector_type, NULL_TREE);
 
       layout_type (temp_type);
       UOBJC_SELECTOR_TABLE_decl
@@ -1320,8 +1296,6 @@ synth_module_prologue (void)
       TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
     }
 
-  generate_forward_declaration_to_string_table ();
-
   /* Forward declare constant_string_id and constant_string_type.  */
   if (!constant_string_class_name)
     constant_string_class_name = default_constant_string_class_name;
@@ -1392,10 +1366,11 @@ my_build_string (int len, const char *str)
    NXConstantString class object.  */
 
 tree
-build_objc_string_object (tree string)
+objc_build_string_object (tree string)
 {
   tree initlist, constructor, constant_string_class;
   int length;
+  tree fields;
 
   string = fix_string_type (string);
 
@@ -1425,6 +1400,7 @@ build_objc_string_object (tree string)
        }
       add_class_reference (constant_string_id);
     }
+  fields = TYPE_FIELDS (constant_string_type);
 
   /* & ((NXConstantString) { NULL, string, length })  */
 
@@ -1440,18 +1416,23 @@ build_objc_string_object (tree string)
          return error_mark_node;
        }
       initlist = build_tree_list
-       (NULL_TREE,
+       (fields,
         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 (fields, build_int_cst (NULL_TREE, 0));
     }
 
+  fields = TREE_CHAIN (fields);
+  
   initlist
-    = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
+    = tree_cons (fields, copy_node (build_unary_op (ADDR_EXPR, string, 1)),
                 initlist);
-  initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist);
+                 
+  fields = TREE_CHAIN (fields);
+  
+  initlist = tree_cons (fields, build_int_cst (NULL_TREE, length), initlist);
   constructor = objc_build_constructor (constant_string_type,
                                        nreverse (initlist));
 
@@ -1461,7 +1442,9 @@ build_objc_string_object (tree string)
        = objc_add_static_instance (constructor, constant_string_type);
     }
 
-  return (build_unary_op (ADDR_EXPR, constructor, 1));
+  constructor = build_unary_op (ADDR_EXPR, constructor, 1);
+  TREE_CONSTANT (constructor) = true;
+  return constructor;
 }
 
 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
@@ -1496,7 +1479,7 @@ objc_add_static_instance (tree constructor, tree class_decl)
      Postpone till end of input.  */
   DECL_DEFER_OUTPUT (decl) = 1;
   pushdecl_top_level (decl);
-  rest_of_decl_compilation (decl, 0, 1, 0);
+  rest_of_decl_compilation (decl, 1, 0);
 
   /* Add the DECL to the head of this CLASS' list.  */
   TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
@@ -1574,7 +1557,7 @@ build_objc_symtab_template (void)
   /* SEL *refs; */
 
   field_decl = create_builtin_decl (FIELD_DECL,
-                                   build_pointer_type (selector_type),
+                                   build_pointer_type (objc_selector_type),
                                    "refs");
   chainon (field_decl_chain, field_decl);
 
@@ -1602,7 +1585,7 @@ build_objc_symtab_template (void)
                   (FIELD_DECL,
                    build_array_type
                    (ptr_type_node,
-                    build_index_type (build_int_2 (index, 0))),
+                    build_index_type (build_int_cst (NULL_TREE, index))),
                    "defs");
       chainon (field_decl_chain, field_decl);
     }
@@ -1647,7 +1630,7 @@ init_def_list (tree type)
       if (static_instances_decl)
        expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
       else
-       expr = build_int_2 (0, 0);
+       expr = build_int_cst (NULL_TREE, 0);
 
       initlist = tree_cons (NULL_TREE, expr, initlist);
     }
@@ -1664,12 +1647,12 @@ init_objc_symtab (tree type)
 
   /* sel_ref_cnt = { ..., 5, ... } */
 
-  initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
+  initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
 
   /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
 
   if (flag_next_runtime || ! sel_ref_chain)
-    initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
   else
     initlist = tree_cons (NULL_TREE,
                          build_unary_op (ADDR_EXPR,
@@ -1678,11 +1661,11 @@ init_objc_symtab (tree type)
 
   /* cls_def_cnt = { ..., 5, ... } */
 
-  initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist);
+  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, imp_count), initlist);
 
   /* cat_def_cnt = { ..., 5, ... } */
 
-  initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist);
+  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, cat_count), initlist);
 
   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
 
@@ -1783,7 +1766,7 @@ init_module_descriptor (tree type)
 
   /* version = { 1, ... } */
 
-  expr = build_int_2 (OBJC_VERSION, 0);
+  expr = build_int_cst (NULL_TREE, OBJC_VERSION);
   initlist = build_tree_list (NULL_TREE, expr);
 
   /* size = { ..., sizeof (struct objc_module), ... } */
@@ -1801,7 +1784,7 @@ init_module_descriptor (tree type)
   if (UOBJC_SYMBOLS_decl)
     expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
   else
-    expr = build_int_2 (0, 0);
+    expr = build_int_cst (NULL_TREE, 0);
   initlist = tree_cons (NULL_TREE, expr, initlist);
 
   return objc_build_constructor (type, nreverse (initlist));
@@ -1872,6 +1855,8 @@ build_module_descriptor (void)
 
   /* Mark the decl to avoid "defined but not used" warning.  */
   DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1;
+  
+  mark_decl_referenced (UOBJC_MODULES_decl);
 
   /* Generate a constructor call for the module descriptor.
      This code was generated by reading the grammar rules
@@ -1883,7 +1868,7 @@ build_module_descriptor (void)
 
   {
     tree parms, execclass_decl, decelerator, void_list_node_1;
-    tree init_function_name, init_function_decl;
+    tree init_function_name, init_function_decl, compound;
 
     /* Declare void __objc_execClass (void *); */
 
@@ -1892,13 +1877,13 @@ build_module_descriptor (void)
                                 get_identifier (TAG_EXECCLASS),
                                 build_function_type (void_type_node,
                                        tree_cons (NULL_TREE, ptr_type_node,
-                                                  OBJC_VOID_AT_END)));
+                                                  void_list_node)));
                                                
     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);
+    rest_of_decl_compilation (execclass_decl, 0, 0);
     assemble_external (execclass_decl);
 
     /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);}  */
@@ -1907,10 +1892,11 @@ build_module_descriptor (void)
     start_function (void_list_node_1,
                    build_nt (CALL_EXPR, init_function_name,
                              tree_cons (NULL_TREE, NULL_TREE,
-                                        OBJC_VOID_AT_END),
+                                        void_list_node),
                              NULL_TREE),
                    NULL_TREE);
     store_parm_decls ();
+    compound = c_begin_compound_stmt (true);
 
     init_function_decl = current_function_decl;
     TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
@@ -1918,15 +1904,14 @@ build_module_descriptor (void)
     /* 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);
 
-    c_expand_expr_stmt (decelerator);
+    add_stmt (decelerator);
+    add_stmt (c_end_compound_stmt (compound, true));
 
     finish_function ();
 
@@ -1934,22 +1919,6 @@ build_module_descriptor (void)
   }
 }
 
-/* extern const char _OBJC_STRINGS[]; */
-
-static void
-generate_forward_declaration_to_string_table (void)
-{
-  tree sc_spec, decl_specs, expr_decl;
-
-  sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
-  decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
-
-  expr_decl
-    = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
-
-  UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
-}
-
 /* Return the DECL of the string IDENT in the SECTION.  */
 
 static tree
@@ -1982,7 +1951,7 @@ generate_static_references (void)
 {
   tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE;
   tree class_name, class, decl, initlist;
-  tree cl_chain, in_chain, type;
+  tree cl_chain, in_chain;
   int num_inst, num_class;
   char buf[256];
 
@@ -1998,13 +1967,14 @@ generate_static_references (void)
       sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
       ident = get_identifier (buf);
 
-      expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
+      expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE);
       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);
       DECL_CONTEXT (decl) = 0;
       DECL_ARTIFICIAL (decl) = 1;
+      TREE_USED (decl) = 1;
 
       /* Output {class_name, ...}.  */
       class = TREE_VALUE (cl_chain);
@@ -2021,23 +1991,17 @@ generate_static_references (void)
        }
 
       /* Output {..., NULL}.  */
-      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+      initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
 
       expr = objc_build_constructor (TREE_TYPE (decl), nreverse (initlist));
       finish_decl (decl, expr, NULL_TREE);
-      TREE_USED (decl) = 1;
-
-      type = build_array_type (build_pointer_type (void_type_node), 0);
-      decl = build_decl (VAR_DECL, ident, type);
-      TREE_USED (decl) = 1;
-      TREE_STATIC (decl) = 1;
       decls
        = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls);
     }
 
-  decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls);
+  decls = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), decls);
   ident = get_identifier ("_OBJC_STATIC_INSTANCES");
-  expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE);
+  expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE, NULL_TREE, NULL_TREE);
   decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node),
                         build_tree_list (NULL_TREE,
                                          ridpointers[(int) RID_STATIC]));
@@ -2049,6 +2013,7 @@ generate_static_references (void)
   expr = objc_build_constructor (TREE_TYPE (static_instances_decl),
                            nreverse (decls));
   finish_decl (static_instances_decl, expr, NULL_TREE);
+  rest_of_decl_compilation (static_instances_decl, 0, 0);
 }
 
 /* Output all strings.  */
@@ -2067,7 +2032,8 @@ generate_strings (void)
       sc_spec
        = 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);
+      expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
+                           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,
@@ -2082,7 +2048,8 @@ generate_strings (void)
       sc_spec
        = 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);
+      expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
+                           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,
@@ -2097,7 +2064,8 @@ generate_strings (void)
       sc_spec
        = 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);
+      expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE,
+                           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,
@@ -2118,14 +2086,14 @@ build_selector_reference_decl (void)
 
   ident = get_identifier (buf);
 
-  decl = build_decl (VAR_DECL, ident, selector_type);
+  decl = build_decl (VAR_DECL, ident, objc_selector_type);
   DECL_EXTERNAL (decl) = 1;
   TREE_PUBLIC (decl) = 0;
   TREE_USED (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
   DECL_CONTEXT (decl) = 0;
 
-  make_decl_rtl (decl, 0);
+  make_decl_rtl (decl);
   pushdecl_top_level (decl);
 
   return decl;
@@ -2140,7 +2108,7 @@ build_selector (tree ident)
   if (flag_typed_selectors)
     return expr;
   else
-    return build_c_cast (selector_type, expr); /* cast! */
+    return build_c_cast (objc_selector_type, expr); /* cast! */
 }
 
 static void
@@ -2190,7 +2158,7 @@ build_selector_translation_table (void)
          sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]);
 
          /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
-         decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec);
+         decl_specs = tree_cons (NULL_TREE, objc_selector_type, sc_spec);
 
          var_decl = name;
 
@@ -2226,7 +2194,7 @@ build_selector_translation_table (void)
       DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0;
       TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1;
       /* NULL terminate the list and fix the decl for output.  */
-      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+      initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
       DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = objc_ellipsis_node;
       initlist = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
                                         nreverse (initlist));
@@ -2252,7 +2220,7 @@ get_proto_encoding (tree proto)
       return add_objc_string (encoding, meth_var_types);
     }
   else
-    return build_int_2 (0, 0);
+    return build_int_cst (NULL_TREE, 0);
 }
 
 /* sel_ref_chain is a list whose "value" fields will be instances of
@@ -2279,9 +2247,9 @@ build_typed_selector_reference (tree ident, tree prototype)
  return_at_index:
   expr = build_unary_op (ADDR_EXPR,
                         build_array_ref (UOBJC_SELECTOR_TABLE_decl,
-                                         build_int_2 (index, 0)),
+                                         build_int_cst (NULL_TREE, index)),
                         1);
-  return build_c_cast (selector_type, expr);
+  return build_c_cast (objc_selector_type, expr);
 }
 
 static tree
@@ -2297,7 +2265,7 @@ build_selector_reference (tree ident)
        return (flag_next_runtime
                ? TREE_PURPOSE (*chain)
                : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
-                                  build_int_2 (index, 0)));
+                                  build_int_cst (NULL_TREE, index)));
 
       index++;
       chain = &TREE_CHAIN (*chain);
@@ -2310,7 +2278,7 @@ build_selector_reference (tree ident)
   return (flag_next_runtime
          ? expr
          : build_array_ref (UOBJC_SELECTOR_TABLE_decl,
-                            build_int_2 (index, 0)));
+                            build_int_cst (NULL_TREE, index)));
 }
 
 static GTY(()) int class_reference_idx;
@@ -2332,7 +2300,7 @@ build_class_reference_decl (void)
   DECL_CONTEXT (decl) = 0;
   DECL_ARTIFICIAL (decl) = 1;
 
-  make_decl_rtl (decl, 0);
+  make_decl_rtl (decl);
   pushdecl_top_level (decl);
 
   return decl;
@@ -2370,7 +2338,7 @@ add_class_reference (tree ident)
    reference variable.  */
 
 tree
-get_class_reference (tree ident)
+objc_get_class_reference (tree ident)
 {
   tree orig_ident;
 
@@ -2383,7 +2351,7 @@ get_class_reference (tree ident)
 #endif
   orig_ident = ident;
 
-  if (!(ident = is_class_name (ident)))
+  if (!(ident = objc_is_class_name (ident)))
     {
       error ("`%s' is not an Objective-C class name or alias",
             IDENTIFIER_POINTER (orig_ident));
@@ -2482,7 +2450,7 @@ build_objc_string_decl (enum string_section section)
   DECL_CONTEXT (decl) = 0;
   DECL_ARTIFICIAL (decl) = 1;
 
-  make_decl_rtl (decl, 0);
+  make_decl_rtl (decl);
   pushdecl_top_level (decl);
 
   return decl;
@@ -2500,9 +2468,9 @@ objc_declare_alias (tree alias_ident, tree class_ident)
   }
 #endif /* OBJCPLUS */
 
-  if (!(underlying_class = is_class_name (class_ident)))
+  if (!(underlying_class = objc_is_class_name (class_ident)))
     warning ("cannot find class `%s'", IDENTIFIER_POINTER (class_ident));
-  else if (is_class_name (alias_ident))
+  else if (objc_is_class_name (alias_ident))
     warning ("class `%s' already exists", IDENTIFIER_POINTER (alias_ident));
   else
     alias_chain = tree_cons (underlying_class, alias_ident, alias_chain);
@@ -2522,7 +2490,7 @@ objc_declare_class (tree ident_list)
     {
       tree ident = TREE_VALUE (list);
 
-      if (! is_class_name (ident))
+      if (! objc_is_class_name (ident))
        {
          tree record = lookup_name (ident);
        
@@ -2542,7 +2510,7 @@ objc_declare_class (tree ident_list)
 }
 
 tree
-is_class_name (tree ident)
+objc_is_class_name (tree ident)
 {
   tree chain;
 
@@ -2590,15 +2558,15 @@ objc_is_object_ptr (tree type)
   if (!type || TREE_CODE (type) != POINTER_TYPE)
     return 0;
   /* NB: This function may be called before the ObjC front-end has
-     been initialized, in which case ID_TYPE will be NULL.  */
-  if (id_type && type && TYPE_P (type)
+     been initialized, in which case OBJC_ID_TYPE will be NULL.  */
+  if (objc_id_type && type && TYPE_P (type)
       && (IS_ID (type)
          || TREE_TYPE (type) == TREE_TYPE (objc_class_type)))
     return type;
-  return is_class_name (OBJC_TYPE_NAME (TREE_TYPE (type)));
+  return objc_is_class_name (OBJC_TYPE_NAME (TREE_TYPE (type)));
 }
 
-tree
+static tree
 lookup_interface (tree ident)
 {
   tree chain;
@@ -2618,7 +2586,7 @@ lookup_interface (tree ident)
 /* Implement @defs (<classname>) within struct bodies.  */
 
 tree
-get_class_ivars_from_name (tree class_name)
+objc_get_class_ivars (tree class_name)
 {
   tree interface = lookup_interface (class_name);
   tree field, fields = NULL_TREE;
@@ -2706,582 +2674,561 @@ get_class_ivars (tree interface, int raw)
 }
 
 static tree
-objc_enter_block (void)
-{
-  tree block;
-
-#ifdef OBJCPLUS
-  block = begin_compound_stmt (0);
-#else
-  block = c_begin_compound_stmt ();
-  pushlevel (0);
-  clear_last_expr ();
-  add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
-#endif
-
-  objc_exception_block_stack = tree_cons (NULL_TREE, block,
-                                         objc_exception_block_stack);
-
-  blk_nesting_count++;
-  return block;
-}
-
-static tree
-objc_exit_block (void)
-{
-  tree block = TREE_VALUE (objc_exception_block_stack);
-#ifndef OBJCPLUS
-  tree scope_stmt, inner;
-#endif
-
-  objc_clear_super_receiver ();
-#ifdef OBJCPLUS
-  finish_compound_stmt (0, block);
-#else
-  scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
-  inner = poplevel (KEEP_MAYBE, 1, 0);
-
-  SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
-       = SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
-       = inner;
-  RECHAIN_STMTS (block, COMPOUND_BODY (block));
-#endif
-  last_expr_type = NULL_TREE;
-  objc_exception_block_stack = TREE_CHAIN (objc_exception_block_stack);        
-
-  blk_nesting_count--;
-  return block;
-}
-
-static tree
-objc_declare_variable (enum rid scspec, tree name, tree type, tree init)
+objc_create_temporary_var (tree type)
 {
   tree decl;
-
-  type = tree_cons (NULL_TREE, type,
-                   tree_cons (NULL_TREE, ridpointers[(int) scspec],
-                              NULL_TREE));
-  TREE_STATIC (type) = 1;
-  decl = start_decl (name, type, (init != NULL_TREE), NULL_TREE);
-  finish_decl (decl, init, NULL_TREE);
-  /* This prevents `unused variable' warnings when compiling with -Wall.  */
+  decl = build_decl (VAR_DECL, NULL_TREE, type);
   TREE_USED (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
+  DECL_IGNORED_P (decl) = 1;
+  DECL_CONTEXT (decl) = current_function_decl;
+
   return decl;
 }
+\f
+/* Exception handling constructs.  We begin by having the parser do most
+   of the work and passing us blocks.  What we do next depends on whether
+   we're doing "native" exception handling or legacy Darwin setjmp exceptions.
+   We abstract all of this in a handful of appropriately named routines.  */
 
-tree
-objc_build_throw_stmt (tree throw_expr)
+/* Stack of open try blocks.  */
+
+struct objc_try_context
 {
-  tree func_params;
+  struct objc_try_context *outer;
 
-  if (!flag_objc_exceptions)
-    fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
+  /* Statements (or statement lists) as processed by the parser.  */
+  tree try_body;
+  tree finally_body;
 
-  if (!throw_expr && objc_caught_exception)
-    throw_expr = TREE_VALUE (objc_caught_exception);
+  /* Some file position locations.  */
+  location_t try_locus;
+  location_t end_try_locus;
+  location_t end_catch_locus;
+  location_t finally_locus;
+  location_t end_finally_locus;
 
-  if (!throw_expr)
-    {
-      error ("`@throw;' (rethrow) used outside of a `@catch' block");
-      return error_mark_node;
-    }
+  /* A STATEMENT_LIST of CATCH_EXPRs, appropriate for sticking into op1
+     of a TRY_CATCH_EXPR.  Even when doing Darwin setjmp.  */
+  tree catch_list;
 
-  func_params = tree_cons (NULL_TREE, throw_expr, NULL_TREE);
+  /* The CATCH_EXPR of an open @catch clause.  */
+  tree current_catch;
 
-  assemble_external (objc_exception_throw_decl);
-  return c_expand_expr_stmt (build_function_call (objc_exception_throw_decl,
-                                                 func_params));
-}
+  /* The VAR_DECL holding the Darwin equivalent of EXC_PTR_EXPR.  */
+  tree caught_decl;
+  tree stack_decl;
+  tree rethrow_decl;
+};
 
-static void
-val_stack_push (struct val_stack **nc, long val)
-{
-  struct val_stack *new_elem = xmalloc (sizeof (struct val_stack));
-  new_elem->val = val;
-  new_elem->next = *nc;
-  *nc = new_elem;
-}
+static struct objc_try_context *cur_try_context;
 
-static void
-val_stack_pop (struct val_stack **nc)
+/* This hook, called via lang_eh_runtime_type, generates a runtime object
+   that represents TYPE.  For Objective-C, this is just the class name.  */
+/* ??? Isn't there a class object or some such?  Is it easy to get?  */
+
+static tree
+objc_eh_runtime_type (tree type)
 {
-  struct val_stack *old_elem = *nc;
-  *nc = old_elem->next;
-  free (old_elem);
+  return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
 }
 
+/* Initialize exception handling.  */
+
 static void
-objc_build_try_enter_fragment (void)
+objc_init_exceptions (void)
 {
-  /* objc_exception_try_enter(&_stackExceptionData);
-     if (!_setjmp(&_stackExceptionData.buf)) {  */
-
-  tree func_params, if_stmt, cond;
+  static bool done = false;
+  if (done)
+    return;
+  done = true;
 
-  func_params
-    = tree_cons (NULL_TREE,
-                build_unary_op (ADDR_EXPR,
-                                TREE_VALUE (objc_stack_exception_data),
-                                0),
-                NULL_TREE);
+  /* Why?  */
+  if (!flag_objc_exceptions)
+    warning ("use %<-fobjc-exceptions%> to enable Objective-C "
+            "exception syntax");
 
-  assemble_external (objc_exception_try_enter_decl);
-  c_expand_expr_stmt (build_function_call
-                     (objc_exception_try_enter_decl, func_params));
-
-  if_stmt = c_begin_if_stmt ();
-  if_nesting_count++;
-  /* If <setjmp.h> has been included, the _setjmp prototype has
-     acquired a real, breathing type for its parameter.  Cast our
-     argument to that type.  */
-  func_params
-    = tree_cons (NULL_TREE,
-                build_c_cast (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))
-                              ? TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl)))
-                              : ptr_type_node,
-                              build_unary_op
-                              (ADDR_EXPR,
-                               build_component_ref (TREE_VALUE (objc_stack_exception_data),
-                                                    get_identifier ("buf")), 0)),
-                NULL_TREE);
-  assemble_external (objc_setjmp_decl);
-  cond = build_unary_op (TRUTH_NOT_EXPR,
-                        build_function_call (objc_setjmp_decl, func_params),
-                        0);
-  c_expand_start_cond (c_common_truthvalue_conversion (cond),
-                      0, if_stmt);
-  objc_enter_block ();
+  if (!flag_objc_sjlj_exceptions)
+    {
+      c_eh_initialized_p = true;
+      eh_personality_libfunc
+       = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+                           ? "__gnu_objc_personality_sj0"
+                           : "__gnu_objc_personality_v0");
+      using_eh_for_cleanups ();
+      lang_eh_runtime_type = objc_eh_runtime_type;
+    }
 }
 
+/* Build an EXC_PTR_EXPR, or the moral equivalent.  In the case of Darwin,
+   we'll arrange for it to be initialized (and associated with a binding)
+   later.  */
+
 static tree
-objc_build_extract_expr (void)
+objc_build_exc_ptr (void)
 {
-  /*   ... = objc_exception_extract(&_stackExceptionData);  */
+  if (flag_objc_sjlj_exceptions)
+    {
+      tree var = cur_try_context->caught_decl;
+      if (!var)
+       {
+         var = objc_create_temporary_var (objc_id_type);
+         cur_try_context->caught_decl = var;
+       }
+      return var;
+    }
+  else
+    return build (EXC_PTR_EXPR, objc_id_type);
+}
 
-  tree func_params
-    = tree_cons (NULL_TREE,
-                build_unary_op (ADDR_EXPR,
-                                TREE_VALUE (objc_stack_exception_data), 0),
-                NULL_TREE);
+/* Build "objc_exception_try_exit(&_stack)".  */
 
-  assemble_external (objc_exception_extract_decl);
-  return build_function_call (objc_exception_extract_decl, func_params);
+static tree
+next_sjlj_build_try_exit (void)
+{
+  tree t;
+  t = build_fold_addr_expr (cur_try_context->stack_decl);
+  t = tree_cons (NULL, t, NULL);
+  t = build_function_call (objc_exception_try_exit_decl, t);
+  return t;
 }
 
-static void
-objc_build_try_exit_fragment (void)
-{
-  /* objc_exception_try_exit(&_stackExceptionData); */
+/* Build
+       objc_exception_try_enter (&_stack);
+       if (_setjmp(&_stack.buf))
+         ;
+       else
+         ;
+   Return the COND_EXPR.  Note that the THEN and ELSE fields are left
+   empty, ready for the caller to fill them in.  */
 
-  tree func_params
-    = tree_cons (NULL_TREE,
-                build_unary_op (ADDR_EXPR,
-                                TREE_VALUE (objc_stack_exception_data), 0),
-                NULL_TREE);
+static tree
+next_sjlj_build_enter_and_setjmp (void)
+{
+  tree t, enter, sj, cond;
 
-    assemble_external (objc_exception_try_exit_decl);
-    c_expand_expr_stmt (build_function_call (objc_exception_try_exit_decl,
-                                            func_params));
-}
+  t = build_fold_addr_expr (cur_try_context->stack_decl);
+  t = tree_cons (NULL, t, NULL);
+  enter = build_function_call (objc_exception_try_enter_decl, t);
 
-static void
-objc_build_extract_fragment (void)
-{
-  /* } else {
-      _rethrowException = objc_exception_extract(&_stackExceptionData);
-     }  */
+  t = build_component_ref (cur_try_context->stack_decl,
+                          get_identifier ("buf"));
+  t = build_fold_addr_expr (t);
+  t = convert (ptr_type_node, t);
+  t = tree_cons (NULL, t, NULL);
+  sj = build_function_call (objc_setjmp_decl, t);
 
-  objc_exit_block ();
-  c_finish_then ();
+  cond = build (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
+  cond = lang_hooks.truthvalue_conversion (cond);
 
-  c_expand_start_else ();
-  objc_enter_block ();
-  c_expand_expr_stmt (build_modify_expr
-                     (TREE_VALUE (objc_rethrow_exception),
-                      NOP_EXPR,
-                      objc_build_extract_expr ()));
-  objc_exit_block ();
-  c_finish_else ();
-  c_expand_end_cond ();
-  if_nesting_count--;
+  return build (COND_EXPR, void_type_node, cond, NULL, NULL);
 }
 
-tree
-objc_build_try_prologue (void)
+/* Build
+       DECL = objc_exception_extract(&_stack);
+*/
+   
+static tree
+next_sjlj_build_exc_extract (tree decl)
 {
-  /* { // new scope
-       struct _objc_exception_data _stackExceptionData;
-       volatile id _rethrowException = nil;
-       { // begin TRY-CATCH scope
-         objc_exception_try_enter(&_stackExceptionData);
-        if (!_setjmp(&_stackExceptionData.buf)) {  */
+  tree t;
 
-  tree try_catch_block;
+  t = build_fold_addr_expr (cur_try_context->stack_decl);
+  t = tree_cons (NULL, t, NULL);
+  t = build_function_call (objc_exception_extract_decl, t);
+  t = convert (TREE_TYPE (decl), t);
+  t = build (MODIFY_EXPR, void_type_node, decl, t);
 
-  if (!flag_objc_exceptions)
-    fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
-
-  objc_mark_locals_volatile ((void *)(exc_binding_stack
-                                     ? exc_binding_stack->val
-                                     : 0));
-  objc_enter_block ();
-  objc_stack_exception_data
-    = tree_cons (NULL_TREE,
-                objc_declare_variable (RID_AUTO,
-                                       get_identifier (UTAG_EXCDATA_VAR),
-                                       xref_tag (RECORD_TYPE,
-                                                 get_identifier (UTAG_EXCDATA)),
-                                       NULL_TREE),
-                objc_stack_exception_data);
-  objc_rethrow_exception = tree_cons (NULL_TREE,
-                                     objc_declare_variable (RID_VOLATILE,
-                                                            get_identifier (UTAG_RETHROWEXC_VAR),
-                                                            id_type,
-                                                            build_int_2 (0, 0)),
-                                     objc_rethrow_exception);
-
-  try_catch_block = objc_enter_block ();
-  val_stack_push (&exc_binding_stack, (long) get_current_scope ());
-  objc_build_try_enter_fragment ();
-
-  return try_catch_block;
+  return t;
 }
 
-void
-objc_build_try_epilogue (int also_catch_prologue)
+/* Build
+       if (objc_exception_match(obj_get_class(TYPE), _caught)
+         BODY
+       else if (...)
+         ...
+       else
+         {
+           _rethrow = _caught;
+           objc_exception_try_exit(&_stack);
+         }
+   from the sequence of CATCH_EXPRs in the current try context.  */
+
+static tree
+next_sjlj_build_catch_list (void)
 {
-  if (also_catch_prologue)
+  tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
+  tree catch_seq, t;
+  tree *last = &catch_seq;
+  bool saw_id = false;
+
+  for (; !tsi_end_p (i); tsi_next (&i))
     {
-      /* } else {
-          register id _caughtException = objc_exception_extract( &_stackExceptionData);
-          objc_exception_try_enter(&_stackExceptionData);
-          if(!_setjmp(&_stackExceptionData.buf)) {
-            if (0) {  */
+      tree stmt = tsi_stmt (i);
+      tree type = CATCH_TYPES (stmt);
+      tree body = CATCH_BODY (stmt);
 
-      tree if_stmt;
+      if (type == NULL)
+       {
+         *last = body;
+         saw_id = true;
+         break;
+       }
+      else
+       {
+         tree args, cond;
 
-      objc_exit_block ();
-      c_finish_then ();
-               
-      c_expand_start_else ();
-      objc_enter_block ();
-      objc_caught_exception
-       = tree_cons (NULL_TREE,
-                    objc_declare_variable (RID_REGISTER,
-                                           get_identifier (UTAG_CAUGHTEXC_VAR),
-                                           id_type,
-                                           objc_build_extract_expr ()),
-                    objc_caught_exception);
-      objc_build_try_enter_fragment ();
-      val_stack_push (&catch_count_stack, 1);
-      if_stmt = c_begin_if_stmt ();
-      if_nesting_count++;
-      c_expand_start_cond (c_common_truthvalue_conversion (boolean_false_node),
-                          0, if_stmt);
-      objc_enter_block ();
-
-      /* Start a new chain of @catch statements for this @try.  */
-      objc_catch_type = tree_cons (objc_catch_type, NULL_TREE, NULL_TREE);
-    }
-  else
-    {  /* !also_catch_prologue */
+         if (type == error_mark_node)
+           cond = error_mark_node;
+         else
+           {
+             args = tree_cons (NULL, cur_try_context->caught_decl, NULL);
+             t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
+             args = tree_cons (NULL, t, args);
+             t = build_function_call (objc_exception_match_decl, args);
+             cond = lang_hooks.truthvalue_conversion (t);
+           }
+         t = build (COND_EXPR, void_type_node, cond, body, NULL);
+         SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
 
-      /* } else {
-          _rethrowException = objc_exception_extract( &_stackExceptionData);
-        }
-       }  */
-      objc_build_extract_fragment ();
-      objc_exit_block ();
+         *last = t;
+         last = &COND_EXPR_ELSE (t);
+       }
     }
-}
 
-void
-objc_build_catch_stmt (tree catch_expr)
-{
-  /* } else if (objc_exception_match(objc_get_class("SomeClass"), _caughtException)) {
-       register SomeClass *e = _caughtException;  */
-
-  tree if_stmt, cond, func_params, prev_catch, var_name, var_type;
-  int catch_id;
-
-#ifndef OBJCPLUS
-  /* Yet another C/C++ impedance mismatch.  */
-  catch_expr = TREE_PURPOSE (catch_expr);
-#endif
+  if (!saw_id)
+    {
+      t = build (MODIFY_EXPR, void_type_node, cur_try_context->rethrow_decl,
+                cur_try_context->caught_decl);
+      annotate_with_locus (t, cur_try_context->end_catch_locus);
+      append_to_statement_list (t, last);
 
-  var_name = TREE_VALUE (catch_expr);
-  var_type = TREE_VALUE (TREE_PURPOSE (catch_expr));
-  if (TREE_CODE (var_name) == INDIRECT_REF)
-    var_name = TREE_OPERAND (var_name, 0);
-  if (TREE_CODE (var_type) == TYPE_DECL
-      || TREE_CODE (var_type) == POINTER_TYPE)
-    var_type = TREE_TYPE (var_type);
-  catch_id = (var_type == TREE_TYPE (id_type));
+      t = next_sjlj_build_try_exit ();
+      annotate_with_locus (t, cur_try_context->end_catch_locus);
+      append_to_statement_list (t, last);
+    }
 
-  if (!flag_objc_exceptions)
-    fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
+  return catch_seq;
+}
 
-  if (!(catch_id || TYPED_OBJECT (var_type)))
-    fatal_error ("`@catch' parameter is not a known Objective-C class type");
+/* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
+   exception handling.  We aim to build:
 
-  /* Examine previous @catch clauses for the current @try block for
-     superclasses of the 'var_type' class.  */
-  for (prev_catch = objc_catch_type; TREE_VALUE (prev_catch);
-       prev_catch = TREE_CHAIN (prev_catch))
-    {
-      if (TREE_VALUE (prev_catch) == TREE_TYPE (id_type))
        {
-         warning ("Exception already handled by preceding `@catch(id)'");
-         break;
+         struct _objc_exception_data _stack;
+         id volatile _rethrow = 0;
+         try
+           {
+             objc_exception_try_enter (&_stack);
+             if (_setjmp(&_stack.buf))
+               {
+                 id _caught = objc_exception_extract(&_stack);
+                 objc_exception_try_enter (&_stack);
+                 if (_setjmp(&_stack.buf))
+                   _rethrow = objc_exception_extract(&_stack);
+                 else
+                   CATCH-LIST
+               }
+             else
+               TRY-BLOCK
+           }
+         finally
+           {
+             if (!_rethrow)
+               objc_exception_try_exit(&_stack);
+             FINALLY-BLOCK
+             if (_rethrow)
+               objc_exception_throw(_rethrow);
+           }
        }
-      else if (!catch_id
-              && objc_comptypes (TREE_VALUE (prev_catch), var_type, 0) == 1)
-       warning ("Exception of type `%s *' already handled by `@catch (%s *)'",
-                IDENTIFIER_POINTER (OBJC_TYPE_NAME (var_type)),
-                IDENTIFIER_POINTER (OBJC_TYPE_NAME (TREE_VALUE (prev_catch))));
-    }
 
-  objc_catch_type = tree_cons (NULL_TREE, var_type, objc_catch_type);
+   If CATCH-LIST is empty, we can omit all of the block containing
+   "_caught" except for the setting of _rethrow.  Note the use of
+   a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
+   but handles goto and other exits from the block.  */
 
-  objc_exit_block ();
-  c_finish_then ();
+static tree
+next_sjlj_build_try_catch_finally (void)
+{
+  tree rethrow_decl, stack_decl, t;
+  tree catch_seq, try_fin, bind;
 
-  c_expand_start_else ();
-  catch_count_stack->val++;
-  if_stmt = c_begin_if_stmt ();
-  if_nesting_count++;
+  /* Create the declarations involved.  */
+  t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
+  stack_decl = objc_create_temporary_var (t);
+  cur_try_context->stack_decl = stack_decl;
 
-  if (catch_id)
-    cond = integer_one_node;
-  else
-    {
-      cond = get_class_reference (OBJC_TYPE_NAME (var_type));
-       
-      func_params
-       = tree_cons (NULL_TREE, cond,
-                    tree_cons (NULL_TREE,
-                               TREE_VALUE (objc_caught_exception),
-                               NULL_TREE));
-      assemble_external (objc_exception_match_decl);
-      cond = build_function_call (objc_exception_match_decl, func_params);
-    }
+  rethrow_decl = objc_create_temporary_var (objc_id_type);
+  cur_try_context->rethrow_decl = rethrow_decl;
+  TREE_THIS_VOLATILE (rethrow_decl) = 1;
+  TREE_CHAIN (rethrow_decl) = stack_decl;
 
-  c_expand_start_cond (c_common_truthvalue_conversion (cond),
-                      0, if_stmt);
-  objc_enter_block ();
-  objc_declare_variable (RID_REGISTER, var_name,
-                        build_pointer_type (var_type),
-                        TREE_VALUE (objc_caught_exception));
-}
+  /* Build the outermost varible binding level.  */
+  bind = build (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
+  annotate_with_locus (bind, cur_try_context->try_locus);
+  TREE_SIDE_EFFECTS (bind) = 1;
 
-void
-objc_build_catch_epilogue (void)
-{
-  /*     } else {
-           _rethrowException = _caughtException;
-           objc_exception_try_exit(&_stackExceptionData);
-         }
-       } else {
-         _rethrowException = objc_exception_extract(&_stackExceptionData);
-       }
-     }
-   } // end TRY-CATCH scope
-  */
+  /* Initialize rethrow_decl.  */
+  t = build (MODIFY_EXPR, void_type_node, rethrow_decl,
+            convert (objc_id_type, null_pointer_node));
+  annotate_with_locus (t, cur_try_context->try_locus);
+  append_to_statement_list (t, &BIND_EXPR_BODY (bind));
 
-  objc_exit_block ();
-  c_finish_then ();
+  /* Build the outermost TRY_FINALLY_EXPR.  */
+  try_fin = build (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
+  annotate_with_locus (try_fin, cur_try_context->try_locus);
+  TREE_SIDE_EFFECTS (try_fin) = 1;
+  append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
 
-  c_expand_start_else ();
-  objc_enter_block ();
-  c_expand_expr_stmt
-    (build_modify_expr
-     (TREE_VALUE (objc_rethrow_exception),
-      NOP_EXPR,
-      TREE_VALUE (objc_caught_exception)));
-  objc_build_try_exit_fragment ();     
-  objc_exit_block ();
-  while (catch_count_stack->val--)
+  /* Create the complete catch sequence.  */
+  if (cur_try_context->catch_list)
     {
-      c_finish_else ();                /* close off all the nested ifs ! */
-      c_expand_end_cond ();
-      if_nesting_count--;
+      tree caught_decl = objc_build_exc_ptr ();
+      catch_seq = build_stmt (BIND_EXPR, caught_decl, NULL, NULL);
+
+      t = next_sjlj_build_exc_extract (caught_decl);
+      append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
+
+      t = next_sjlj_build_enter_and_setjmp ();
+      COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (rethrow_decl);
+      COND_EXPR_ELSE (t) = next_sjlj_build_catch_list ();
+      append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
     }
-  val_stack_pop (&catch_count_stack);
-  objc_caught_exception = TREE_CHAIN (objc_caught_exception);
+  else
+    catch_seq = next_sjlj_build_exc_extract (rethrow_decl);
+  annotate_with_locus (catch_seq, cur_try_context->end_try_locus);
 
-  objc_build_extract_fragment ();
+  /* Build the main register-and-try if statement.  */
+  t = next_sjlj_build_enter_and_setjmp ();
+  annotate_with_locus (t, cur_try_context->try_locus);
+  COND_EXPR_THEN (t) = catch_seq;
+  COND_EXPR_ELSE (t) = cur_try_context->try_body;
+  TREE_OPERAND (try_fin, 0) = t;
 
-  objc_exit_block ();
-  c_finish_else ();
-  c_expand_end_cond ();
-  if_nesting_count--;
-  objc_exit_block ();
+  /* Build the complete FINALLY statement list.  */
+  t = next_sjlj_build_try_exit ();
+  t = build_stmt (COND_EXPR,
+                 lang_hooks.truthvalue_conversion (rethrow_decl),
+                 NULL, t);
+  annotate_with_locus (t, cur_try_context->finally_locus);
+  append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
 
-  /* Return to enclosing chain of @catch statements (if any).  */
-  while (TREE_VALUE (objc_catch_type))
-    objc_catch_type = TREE_CHAIN (objc_catch_type);
-  objc_catch_type = TREE_PURPOSE (objc_catch_type);
-}
+  append_to_statement_list (cur_try_context->finally_body,
+                           &TREE_OPERAND (try_fin, 1));
 
-tree
-objc_build_finally_prologue ()
-{
-  /* { // begin FINALLY scope
-       if (!_rethrowException) {
-         objc_exception_try_exit(&_stackExceptionData);
-       }  */
+  t = tree_cons (NULL, rethrow_decl, NULL);
+  t = build_function_call (objc_exception_throw_decl, t);
+  t = build_stmt (COND_EXPR,
+                 lang_hooks.truthvalue_conversion (rethrow_decl),
+                 t, NULL);
+  annotate_with_locus (t, cur_try_context->end_finally_locus);
+  append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
 
-  tree blk = objc_enter_block ();
+  return bind;
+}
 
-  tree if_stmt = c_begin_if_stmt ();
-  if_nesting_count++;
+/* Called just after parsing the @try and its associated BODY.  We now
+   must prepare for the tricky bits -- handling the catches and finally.  */
 
-  c_expand_start_cond (c_common_truthvalue_conversion
-                      (build_unary_op
-                       (TRUTH_NOT_EXPR,
-                        TREE_VALUE (objc_rethrow_exception), 0)),
-                      0, if_stmt);
-  objc_enter_block ();
-  objc_build_try_exit_fragment ();
-  objc_exit_block ();
-  c_finish_then ();
-  c_expand_end_cond ();
-  if_nesting_count--;
+void
+objc_begin_try_stmt (location_t try_locus, tree body)
+{
+  struct objc_try_context *c = xcalloc (1, sizeof (*c));
+  c->outer = cur_try_context;
+  c->try_body = body;
+  c->try_locus = try_locus;
+  c->end_try_locus = input_location;
+  cur_try_context = c;
 
-  return blk;
+  objc_init_exceptions ();
 }
 
-tree
-objc_build_finally_epilogue (void)
+/* Called just after parsing "@catch (parm)".  Open a binding level, 
+   enter PARM into the binding level, and initialize it.  Leave the
+   binding level open while the body of the compound statement is parsed.  */
+   
+void
+objc_begin_catch_clause (tree parm)
 {
-  /*    if (_rethrowException) {
-         objc_exception_throw(_rethrowException);
-       }
-      } // end FINALLY scope
-    } */
+  tree compound, decl, type, t;
+
+  /* Begin a new scope that the entire catch clause will live in.  */
+  compound = c_begin_compound_stmt (1);
 
-  tree if_stmt = c_begin_if_stmt ();
-  if_nesting_count++;
+  /* Turn the raw declarator/declspecs into a decl in the current scope.  */
+  decl = define_decl (TREE_VALUE (TREE_PURPOSE (parm)),
+                     TREE_PURPOSE (TREE_PURPOSE (parm)));
 
-  c_expand_start_cond
-    (c_common_truthvalue_conversion (TREE_VALUE (objc_rethrow_exception)),
-     0, if_stmt);
-  objc_enter_block ();
-  objc_build_throw_stmt (TREE_VALUE (objc_rethrow_exception));
-  objc_exit_block ();
-  c_finish_then ();
-  c_expand_end_cond ();
-  if_nesting_count--;
+  /* Since a decl is required here by syntax, don't warn if its unused.  */
+  /* ??? As opposed to __attribute__((unused))?  Anyway, this appears to
+     be what the previous objc implementation did.  */
+  TREE_USED (decl) = 1;
 
-  objc_exit_block ();
-  objc_rethrow_exception = TREE_CHAIN (objc_rethrow_exception);
-  objc_stack_exception_data = TREE_CHAIN (objc_stack_exception_data);
+  /* Verify that the type of the catch is valid.  It must be a pointer
+     to an Objective-C class, or "id" (which is catch-all).  */
+  type = TREE_TYPE (decl);
+  if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
+    type = NULL;
+  else if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
+    {
+      error ("@catch parameter is not a known Objective-C class type");
+      type = error_mark_node;
+    }
+  else if (cur_try_context->catch_list)
+    {
+      /* Examine previous @catch clauses and see if we've already
+        caught the type in question.  */
+      tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
+      for (; !tsi_end_p (i); tsi_next (&i))
+       {
+         tree stmt = tsi_stmt (i);
+         t = CATCH_TYPES (stmt);
+         if (t == error_mark_node)
+           continue;
+         if (!t || objc_comptypes (TREE_TYPE (t), TREE_TYPE (type), 0) == 1)
+           {
+             warning ("exception of type %<%T%> will be caught",
+                      TREE_TYPE (type));
+             warning ("%H   by earlier handler for %<%T%>",
+                      EXPR_LOCUS (stmt), TREE_TYPE (t ? t : objc_id_type));
+             break;
+           }
+       }
+    }
+
+  /* Record the data for the catch in the try context so that we can
+     finalize it later.  */
+  t = build_stmt (CATCH_EXPR, type, compound);
+  cur_try_context->current_catch = t;
 
-  val_stack_pop (&exc_binding_stack);
-  return objc_exit_block ();
+  /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime.  */
+  t = objc_build_exc_ptr ();
+  t = convert (TREE_TYPE (decl), t);
+  t = build (MODIFY_EXPR, void_type_node, decl, t);
+  add_stmt (t);
 }
 
-tree
-objc_build_try_catch_finally_stmt (int has_catch, int has_finally)
-{
-  /* NB: The operative assumption here is that TRY_FINALLY_EXPR will
-     deal with all exits from 'try_catch_blk' and route them through
-     'finally_blk'.  */
-  tree outer_blk = objc_build_finally_epilogue ();
-  tree prec_stmt = TREE_CHAIN (TREE_CHAIN (COMPOUND_BODY (outer_blk)));
-  tree try_catch_blk = TREE_CHAIN (prec_stmt), try_catch_expr;
-  tree finally_blk = TREE_CHAIN (try_catch_blk), finally_expr;
-  tree succ_stmt = TREE_CHAIN (finally_blk);
-  tree try_finally_stmt, try_finally_expr;
+/* Called just after parsing the closing brace of a @catch clause.  Close
+   the open binding level, and record a CATCH_EXPR for it.  */
 
-  if (!flag_objc_exceptions)
-    fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
+void
+objc_finish_catch_clause (void)
+{
+  tree c = cur_try_context->current_catch;
+  cur_try_context->current_catch = NULL;
+  cur_try_context->end_catch_locus = input_location;
 
-  /* It is an error to have a @try block without a @catch and/or @finally
-     (even though sensible code can be generated nonetheless).  */
+  CATCH_BODY (c) = c_end_compound_stmt (CATCH_BODY (c), 1);
+  append_to_statement_list (c, &cur_try_context->catch_list);
+}
 
-  if (!has_catch && !has_finally)
-    error ("`@try' without `@catch' or `@finally'");
+/* Called after parsing a @finally clause and its associated BODY.
+   Record the body for later placement.  */
 
-  /* We shall now do something truly disgusting.  We shall remove the
-     'try_catch_blk' and 'finally_blk' from the 'outer_blk' statement
-     chain, and replace them with a TRY_FINALLY_EXPR statement!  If
-     this doesn't work, we will have to learn (from Per/gcj) how to
-     construct the 'outer_blk' lazily.  */
-
-  TREE_CHAIN (try_catch_blk) = TREE_CHAIN (finally_blk) = NULL_TREE;
-  try_catch_expr = build1 (STMT_EXPR, void_type_node, try_catch_blk);
-  TREE_SIDE_EFFECTS (try_catch_expr) = 1;
-  finally_expr = build1 (STMT_EXPR, void_type_node, finally_blk);
-  TREE_SIDE_EFFECTS (finally_expr) = 1;
-  try_finally_expr = build (TRY_FINALLY_EXPR, void_type_node, try_catch_expr,
-                           finally_expr);
-  TREE_SIDE_EFFECTS (try_finally_expr) = 1;
-  try_finally_stmt = build_stmt (EXPR_STMT, try_finally_expr);
-  TREE_CHAIN (prec_stmt) = try_finally_stmt;
-  TREE_CHAIN (try_finally_stmt) = succ_stmt;
-       
-  return outer_blk;  /* the whole enchilada */
+void
+objc_build_finally_clause (location_t finally_locus, tree body)
+{
+  cur_try_context->finally_body = body;
+  cur_try_context->finally_locus = finally_locus;
+  cur_try_context->end_finally_locus = input_location;
 }
 
+/* Called to finalize a @try construct.  */
+
 void
-objc_build_synchronized_prologue (tree sync_expr)
+objc_finish_try_stmt (void)
 {
-  /* {
-       id _eval_once = <sync_expr>;
-       @try {
-              objc_sync_enter( _eval_once );  */
+  struct objc_try_context *c = cur_try_context;
+  tree stmt;
 
-  tree func_params;
+  if (c->catch_list == NULL && c->finally_body == NULL)
+    error ("`@try' without `@catch' or `@finally'");
 
-  if (!flag_objc_exceptions)
-    fatal_error ("Use `-fobjc-exceptions' to enable Objective-C exception syntax");
-
-  objc_enter_block ();
-  objc_eval_once
-    = tree_cons (NULL_TREE,
-                objc_declare_variable (RID_AUTO,
-                                       get_identifier (UTAG_EVALONCE_VAR),
-                                       id_type,
-                                       sync_expr),
-                objc_eval_once);
-  objc_build_try_prologue ();
-  objc_enter_block (); 
-  func_params = tree_cons (NULL_TREE,
-                          TREE_VALUE (objc_eval_once),
-                          NULL_TREE);
+  /* If we're doing Darwin setjmp exceptions, build the big nasty.  */
+  if (flag_objc_sjlj_exceptions)
+    {
+      if (!cur_try_context->finally_body)
+       {
+         cur_try_context->finally_locus = input_location;
+         cur_try_context->end_finally_locus = input_location;
+       }
+      stmt = next_sjlj_build_try_catch_finally ();
+    }
+  else
+    {
+      /* Otherwise, nest the CATCH inside a FINALLY.  */
+      stmt = c->try_body;
+      if (c->catch_list)
+       {
+          stmt = build_stmt (TRY_CATCH_EXPR, stmt, c->catch_list);
+         annotate_with_locus (stmt, cur_try_context->try_locus);
+       }
+      if (c->finally_body)
+       {
+         stmt = build_stmt (TRY_FINALLY_EXPR, stmt, c->finally_body);
+         annotate_with_locus (stmt, cur_try_context->try_locus);
+       }
+    }
+  add_stmt (stmt);
 
-  assemble_external (objc_sync_enter_decl);
-  c_expand_expr_stmt (build_function_call
-                     (objc_sync_enter_decl, func_params));
+  cur_try_context = c->outer;
+  free (c);
 }
 
 tree
-objc_build_synchronized_epilogue (void)
+objc_build_throw_stmt (tree throw_expr)
 {
-  /* }
-       @finally {
-         objc_sync_exit( _eval_once );
-       }
-     }  */
+  tree args;
 
-  tree func_params;
+  objc_init_exceptions ();
 
-  objc_exit_block ();  
-  objc_build_try_epilogue (0);
-  objc_build_finally_prologue ();
-  func_params = tree_cons (NULL_TREE, TREE_VALUE (objc_eval_once),
-                          NULL_TREE);
+  if (throw_expr == NULL)
+    {
+      /* If we're not inside a @catch block, there is no "current
+        exception" to be rethrown.  */
+      if (cur_try_context == NULL
+          || cur_try_context->current_catch == NULL)
+       {
+         error ("%<@throw%> (rethrow) used outside of a @catch block");
+         return NULL_TREE;
+       }
+
+      /* Otherwise the object is still sitting in the EXC_PTR_EXPR
+        value that we get from the runtime.  */
+      throw_expr = objc_build_exc_ptr ();
+    }
+
+  /* A throw is just a call to the runtime throw function with the
+     object as a parameter.  */
+  args = tree_cons (NULL, throw_expr, NULL);
+  return add_stmt (build_function_call (objc_exception_throw_decl, args));
+}
+
+void
+objc_build_synchronized (location_t start_locus, tree mutex, tree body)
+{
+  tree args, call;
+
+  /* First lock the mutex.  */
+  mutex = save_expr (mutex);
+  args = tree_cons (NULL, mutex, NULL);
+  call = build_function_call (objc_sync_enter_decl, args);
+  annotate_with_locus (call, start_locus);
+  add_stmt (call);
 
-  assemble_external (objc_sync_exit_decl);
-  c_expand_expr_stmt (build_function_call (objc_sync_exit_decl,
-                                          func_params));
-  objc_build_try_catch_finally_stmt (0, 1);
+  /* Build the mutex unlock.  */
+  args = tree_cons (NULL, mutex, NULL);
+  call = build_function_call (objc_sync_exit_decl, args);
+  annotate_with_locus (call, input_location);
 
-  return objc_exit_block ();
+  /* Put the that and the body in a TRY_FINALLY.  */
+  objc_begin_try_stmt (start_locus, body);
+  objc_build_finally_clause (input_location, call);
+  objc_finish_try_stmt ();
 }
 
+\f
 /* Predefine the following data type:
 
    struct _objc_exception_data
@@ -3302,7 +3249,7 @@ objc_build_synchronized_epilogue (void)
 #endif
 
 static void
-build_objc_exception_stuff (void)
+build_next_objc_exception_stuff (void)
 {
   tree field_decl, field_decl_chain, index, temp_type;
 
@@ -3313,12 +3260,13 @@ build_objc_exception_stuff (void)
 
   write_symbols = NO_DEBUG;
   debug_hooks = &do_nothing_debug_hooks;
+
   objc_exception_data_template
     = start_struct (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
 
   /* int buf[_JBLEN]; */
 
-  index = build_index_type (build_int_2 (_JBLEN - 1, 0));
+  index = build_index_type (build_int_cst (NULL_TREE, _JBLEN - 1));
   field_decl = create_builtin_decl (FIELD_DECL,
                                    build_array_type (integer_type_node, index),
                                    "buf");
@@ -3326,7 +3274,7 @@ build_objc_exception_stuff (void)
 
   /* void *pointers[4]; */
 
-  index = build_index_type (build_int_2 (4 - 1, 0));
+  index = build_index_type (build_int_cst (NULL_TREE, 4 - 1));
   field_decl = create_builtin_decl (FIELD_DECL,
                                    build_array_type (ptr_type_node, index),
                                    "pointers");
@@ -3335,7 +3283,7 @@ build_objc_exception_stuff (void)
   finish_struct (objc_exception_data_template, field_decl_chain, NULL_TREE);
 
   /* int _setjmp(...); */
-  /* If the user includes <setjmp.h>, this shall be superceded by
+  /* If the user includes <setjmp.h>, this shall be superseded by
      'int _setjmp(jmp_buf);' */
   temp_type = build_function_type (integer_type_node, NULL_TREE);
   objc_setjmp_decl
@@ -3343,10 +3291,10 @@ build_objc_exception_stuff (void)
 
   /* id objc_exception_extract(struct _objc_exception_data *); */
   temp_type
-    = build_function_type (id_type,
+    = build_function_type (objc_id_type,
                           tree_cons (NULL_TREE,
                                      build_pointer_type (objc_exception_data_template),
-                                     OBJC_VOID_AT_END));
+                                     void_list_node));
   objc_exception_extract_decl
     = builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
   /* void objc_exception_try_enter(struct _objc_exception_data *); */
@@ -3355,37 +3303,51 @@ build_objc_exception_stuff (void)
     = build_function_type (void_type_node,
                           tree_cons (NULL_TREE,
                                      build_pointer_type (objc_exception_data_template),
-                                     OBJC_VOID_AT_END));
+                                     void_list_node));
   objc_exception_try_enter_decl
     = builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
   objc_exception_try_exit_decl
     = builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+
+  /* int objc_exception_match(id, id); */
+  temp_type 
+    = build_function_type (integer_type_node,
+                          tree_cons (NULL_TREE, objc_id_type,
+                                     tree_cons (NULL_TREE, objc_id_type,
+                                                void_list_node)));
+  objc_exception_match_decl
+    = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+       
+  write_symbols = save_write_symbols;
+  debug_hooks = save_hooks;
+}
+
+static void
+build_objc_exception_stuff (void)
+{
+  tree noreturn_list, nothrow_list, temp_type;
+
+  noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
+  nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
+
   /* void objc_exception_throw(id) __attribute__((noreturn)); */
   /* void objc_sync_enter(id); */
   /* void objc_sync_exit(id); */
   temp_type = build_function_type (void_type_node,
-                                  tree_cons (NULL_TREE, id_type,
-                                             OBJC_VOID_AT_END));
+                                  tree_cons (NULL_TREE, objc_id_type,
+                                             void_list_node));
   objc_exception_throw_decl
-    = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
-  DECL_ATTRIBUTES (objc_exception_throw_decl)
-    = tree_cons (get_identifier ("noreturn"), NULL_TREE, NULL_TREE);
+    = builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL,
+                       noreturn_list);
   objc_sync_enter_decl
-    = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN,
+                       NULL, nothrow_list);
   objc_sync_exit_decl
-    = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
-  /* int objc_exception_match(id, id); */
-  temp_type = build_function_type (integer_type_node,
-                                  tree_cons (NULL_TREE, id_type,
-                                             tree_cons (NULL_TREE, id_type,
-                                                        OBJC_VOID_AT_END)));
-  objc_exception_match_decl
-    = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
-       
-  write_symbols = save_write_symbols;
-  debug_hooks = save_hooks;
+    = builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN,
+                       NULL, nothrow_list);
 }
 
+
 /* struct <classname> {
      struct objc_class *isa;
      ...
@@ -3414,7 +3376,7 @@ build_private_template (tree class)
       TREE_STATIC_TEMPLATE (uprivate_record) = 1;
     }
 
-  instance_type
+  objc_instance_type
     = groktypename (build_tree_list (build_tree_list (NULL_TREE,
                                                      uprivate_record),
                                     build1 (INDIRECT_REF, NULL_TREE,
@@ -3550,7 +3512,7 @@ build_method_prototype_list_template (tree list_type, int size)
 
   decl_specs = build_tree_list (NULL_TREE, list_type);
   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
-                        build_int_2 (size, 0));
+                        build_int_cst (NULL_TREE, size), NULL_TREE, NULL_TREE);
   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
   chainon (field_decl_chain, field_decl);
 
@@ -3696,7 +3658,7 @@ generate_descriptor_table (tree type, const char *name, int size, tree list,
                     decl_specs, 1, NULL_TREE);
   DECL_CONTEXT (decl) = NULL_TREE;
 
-  initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0));
+  initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
   initlist = tree_cons (NULL_TREE, list, initlist);
 
   finish_decl (decl, objc_build_constructor (type, nreverse (initlist)),
@@ -3906,7 +3868,7 @@ generate_protocols (void)
          TREE_TYPE (refs_expr) = cast_type2;
        }
       else
-       refs_expr = build_int_2 (0, 0);
+       refs_expr = build_int_cst (NULL_TREE, 0);
 
       /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
         by generate_method_descriptors, which is called above.  */
@@ -3939,14 +3901,13 @@ build_protocol_initializer (tree type, tree protocol_name,
   /* Filling the "isa" in with one allows the runtime system to
      detect that the version change...should remove before final release.  */
 
-  expr = build_int_2 (PROTOCOL_VERSION, 0);
-  TREE_TYPE (expr) = cast_type;
+  expr = build_int_cst (cast_type, PROTOCOL_VERSION);
   initlist = tree_cons (NULL_TREE, expr, initlist);
   initlist = tree_cons (NULL_TREE, protocol_name, initlist);
   initlist = tree_cons (NULL_TREE, protocol_list, initlist);
 
   if (!instance_methods)
-    initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
   else
     {
       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
@@ -3954,7 +3915,7 @@ build_protocol_initializer (tree type, tree protocol_name,
     }
 
   if (!class_methods)
-    initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
   else
     {
       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
@@ -4241,6 +4202,9 @@ synth_forward_declarations (void)
   /* static struct objc_class _OBJC_METACLASS_<my_name>; */
   UOBJC_METACLASS_decl = build_metadata_decl ("_OBJC_METACLASS",
                                                  objc_class_template);
+                                                 
+  mark_decl_referenced (UOBJC_CLASS_decl);
+  mark_decl_referenced (UOBJC_METACLASS_decl);
 
   /* Pre-build the following entities - for speed/convenience.  */
 
@@ -4283,7 +4247,17 @@ check_ivars (tree inter, tree imp)
 
       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
 
-      if (!comptypes (t1, t2, false)
+      if (TREE_VALUE (TREE_VALUE (rawimpdecls)))
+       {
+         /* t1 is the bit-field type, so t2 must be converted to the
+            bit-field type for comparison as well.  */
+         unsigned HOST_WIDE_INT width
+           = tree_low_cst (TREE_VALUE (TREE_VALUE (rawimpdecls)), 1);
+         if (width != TYPE_PRECISION (t2))
+           t2 = build_nonstandard_integer_type (width, TYPE_UNSIGNED (t2));
+       }
+
+      if (!comptypes (t1, t2)
          || !tree_int_cst_equal (TREE_VALUE (TREE_VALUE (rawintdecls)),
                                  TREE_VALUE (TREE_VALUE (rawimpdecls))))
        {
@@ -4342,11 +4316,19 @@ build_super_template (void)
   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
   field_decl_chain = field_decl;
 
+#ifdef OBJCPLUS
+  /* struct objc_class *super_class; */
+#else
   /* struct objc_class *class; */
+#endif
 
   decl_specs = get_identifier (UTAG_CLASS);
   decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs));
+#ifdef OBJCPLUS
+  field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class"));
+#else
   field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class"));
+#endif
 
   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
   chainon (field_decl_chain, field_decl);
@@ -4426,7 +4408,7 @@ build_ivar_list_template (tree list_type, int size)
 
   decl_specs = build_tree_list (NULL_TREE, list_type);
   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
-                        build_int_2 (size, 0));
+                        build_int_cst (NULL_TREE, size), NULL_TREE, NULL_TREE);
 
   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
   chainon (field_decl_chain, field_decl);
@@ -4474,7 +4456,7 @@ build_method_list_template (tree list_type, int size)
 
   decl_specs = build_tree_list (NULL_TREE, list_type);
   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
-                        build_int_2 (size, 0));
+                        build_int_cst (NULL_TREE, size), NULL_TREE, NULL_TREE);
 
   field_decl = grokfield (field_decl, decl_specs, NULL_TREE);
   chainon (field_decl_chain, field_decl);
@@ -4501,7 +4483,7 @@ build_ivar_list_initializer (tree type, tree field_decl)
                          ivar);
       else
        /* Unnamed bit-field ivar (yuck).  */
-       ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar);
+       ivar = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), ivar);
 
       /* Set type.  */
       encode_field_decl (field_decl,
@@ -4544,7 +4526,7 @@ generate_ivars_list (tree type, const char *name, int size, tree list)
   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 = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, size));
   initlist = tree_cons (NULL_TREE, list, initlist);
 
   finish_decl (decl,
@@ -4556,8 +4538,7 @@ generate_ivars_list (tree type, const char *name, int size, tree list)
 
 /* Count only the fields occurring in T.  */
 static int
-ivar_list_length (t)
-     tree t;
+ivar_list_length (tree t)
 {
   int count = 0;
 
@@ -4720,8 +4701,8 @@ generate_dispatch_table (tree type, const char *name, int size, tree list)
   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);
+  initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
+  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, size), initlist);
   initlist = tree_cons (NULL_TREE, list, initlist);
 
   finish_decl (decl,
@@ -4853,10 +4834,9 @@ generate_protocol_list (tree i_or_p)
       size++;
 
   /* Build initializer.  */
-  initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE);
+  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), NULL_TREE);
 
-  e = build_int_2 (size, 0);
-  TREE_TYPE (e) = cast_type;
+  e = build_int_cst (cast_type, size);
   initlist = tree_cons (NULL_TREE, e, initlist);
 
   for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
@@ -4882,18 +4862,18 @@ generate_protocol_list (tree i_or_p)
     expr_decl = build_nt (ARRAY_REF,
                          synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS",
                                                      i_or_p),
-                         build_int_2 (size + 2, 0));
+                         build_int_cst (NULL_TREE, size + 2), NULL_TREE, NULL_TREE);
   else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE)
     expr_decl = build_nt (ARRAY_REF,
                          synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS",
                                                      i_or_p),
-                         build_int_2 (size + 2, 0));
+                         build_int_cst (NULL_TREE, size + 2), NULL_TREE, NULL_TREE);
   else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
     expr_decl
       = build_nt (ARRAY_REF,
                  synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS",
                                              i_or_p),
-                 build_int_2 (size + 2, 0));
+                 build_int_cst (NULL_TREE, size + 2), NULL_TREE, NULL_TREE);
   else
     abort ();
 
@@ -4920,14 +4900,14 @@ build_category_initializer (tree type, tree cat_name, tree class_name,
   initlist = tree_cons (NULL_TREE, class_name, initlist);
 
   if (!instance_methods)
-    initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
   else
     {
       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
       initlist = tree_cons (NULL_TREE, expr, initlist);
     }
   if (!class_methods)
-    initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
   else
     {
       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
@@ -4936,7 +4916,7 @@ build_category_initializer (tree type, tree cat_name, tree class_name,
 
   /* protocol_list = */
   if (!protocol_list)
-     initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+     initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
   else
      {
        tree cast_type2 = groktypename
@@ -4995,17 +4975,17 @@ build_shared_structure_initializer (tree type, tree isa, tree super,
   initlist = tree_cons (NULL_TREE, default_conversion (name), initlist);
 
   /* version = */
-  initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
 
   /* info = */
-  initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist);
+  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, status), initlist);
 
   /* instance_size = */
   initlist = tree_cons (NULL_TREE, size, initlist);
 
   /* objc_ivar_list = */
   if (!ivar_list)
-    initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
   else
     {
       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
@@ -5014,7 +4994,7 @@ build_shared_structure_initializer (tree type, tree isa, tree super,
 
   /* objc_method_list = */
   if (!dispatch_table)
-    initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
   else
     {
       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
@@ -5023,22 +5003,22 @@ build_shared_structure_initializer (tree type, tree isa, tree super,
 
   if (flag_next_runtime)
     /* method_cache = */
-    initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
   else
     {
       /* dtable = */
-      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+      initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
 
       /* subclass_list = */
-      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+      initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
 
       /* sibling_class = */
-      initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+      initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
     }
 
   /* protocol_list = */
   if (! protocol_list)
-    initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
   else
      {
        tree cast_type2
@@ -5057,14 +5037,26 @@ build_shared_structure_initializer (tree type, tree isa, tree super,
 
   if (flag_next_runtime)
     /* sel_id = NULL */
-    initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+    initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
 
   /* gc_object_type = NULL */
-  initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
+  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist);
 
   return objc_build_constructor (type, nreverse (initlist));
 }
 
+/* Retrieve category interface CAT_NAME (if any) associated with CLASS.  */
+
+static inline tree
+lookup_category (tree class, tree cat_name)
+{
+  tree category = CLASS_CATEGORY_LIST (class);
+
+  while (category && CLASS_SUPER_NAME (category) != cat_name)
+    category = CLASS_CATEGORY_LIST (category);
+  return category;
+}
+
 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... };  */
 
 static void
@@ -5079,15 +5071,8 @@ generate_category (tree cat)
 
   class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
 
-  category = CLASS_CATEGORY_LIST (implementation_template);
-
-  /* find the category interface from the class it is associated with */
-  while (category)
-    {
-      if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
-       break;
-      category = CLASS_CATEGORY_LIST (category);
-    }
+  category = lookup_category (implementation_template,
+                               CLASS_SUPER_NAME (cat));
 
   if (category && CLASS_PROTOCOL_LIST (category))
     {
@@ -5164,7 +5149,7 @@ generate_shared_structures (void)
       super_expr = build_c_cast (cast_type, super_expr); /* cast! */
     }
   else
-    super_expr = build_int_2 (0, 0);
+    super_expr = build_int_cst (NULL_TREE, 0);
 
   root_expr = add_objc_string (my_root_id, class_names);
   root_expr = build_c_cast (cast_type, root_expr); /* cast! */
@@ -5324,7 +5309,7 @@ adjust_type_for_id_default (tree type)
      Out:      an instance of "keyword_decl".  */
 
 tree
-build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
+objc_build_keyword_decl (tree key_name, tree arg_type, tree arg_name)
 {
   tree keyword_decl;
 
@@ -5443,14 +5428,14 @@ get_arg_type_list (tree meth, int context, int superflag)
 
   /* Receiver type.  */
   if (flag_next_runtime && superflag)
-    arglist = build_tree_list (NULL_TREE, super_type);
+    arglist = build_tree_list (NULL_TREE, objc_super_type);
   else if (context == METHOD_DEF)
     arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl));
   else
-    arglist = build_tree_list (NULL_TREE, id_type);
+    arglist = build_tree_list (NULL_TREE, objc_id_type);
 
   /* Selector type - will eventually change to `int'.  */
-  chainon (arglist, build_tree_list (NULL_TREE, selector_type));
+  chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
 
   /* No actual method prototype given -- assume that remaining arguments
      are `...'.  */
@@ -5466,7 +5451,7 @@ get_arg_type_list (tree meth, int context, int superflag)
 
   if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
     /* We have a `, ...' immediately following the selector,
-       finalize the arglist...simulate get_parm_info (0).  */
+       finalize the arglist...simulate get_parm_info (true).  */
     ;
   else if (METHOD_ADD_ARGS (meth))
     {
@@ -5475,14 +5460,14 @@ get_arg_type_list (tree meth, int context, int superflag)
       chainon (arglist, add_arg_list);
     }
   else
-    /* finalize the arglist...simulate get_parm_info (1) */
-    chainon (arglist, OBJC_VOID_AT_END);
+    /* finalize the arglist...simulate get_parm_info (false) */
+    chainon (arglist, void_list_node);
 
   return arglist;
 }
 
 static tree
-check_duplicates (hash hsh, int methods)
+check_duplicates (hash hsh, int methods, int is_class)
 {
   tree meth = NULL_TREE;
 
@@ -5495,22 +5480,30 @@ check_duplicates (hash hsh, int methods)
          /* We have two or more methods with the same name but
             different types.  */
          attr loop;
-         char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
 
          warning ("multiple %s named `%c%s' found",
-                  methods ? "methods" : "selectors", type,
+                  methods ? "methods" : "selectors",
+                  (is_class ? '+' : '-'),
                   IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
 
-         warn_with_method (methods ? "using" : "found", type, meth);
+         warn_with_method (methods ? "using" : "found",
+                           ((TREE_CODE (meth) == INSTANCE_METHOD_DECL)
+                            ? '-'
+                            : '+'), 
+                           meth);
          for (loop = hsh->list; loop; loop = loop->next)
-           warn_with_method ("also found", type, loop->value);
+           warn_with_method ("also found",
+                             ((TREE_CODE (loop->value) == INSTANCE_METHOD_DECL)
+                              ? '-' 
+                              : '+'),
+                             loop->value);
         }
     }
   return meth;
 }
 
 /* If RECEIVER is a class reference, return the identifier node for
-   the referenced class.  RECEIVER is created by get_class_reference,
+   the referenced class.  RECEIVER is created by objc_get_class_reference,
    so we check the exact form created depending on which runtimes are
    used.  */
 
@@ -5547,7 +5540,7 @@ receiver_is_class_object (tree receiver, int self, int super)
       && (exp = TREE_OPERAND (exp, 0))
       && TREE_CODE (exp) == FUNCTION_DECL
       /* For some reason, we sometimes wind up with multiple FUNCTION_DECL
-        prototypes for objc_get_class().  Thankfuly, they seem to share the
+        prototypes for objc_get_class().  Thankfully, they seem to share the
         same function type.  */
       && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
       && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
@@ -5586,7 +5579,7 @@ objc_message_selector (void)
    (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...);  */
 
 tree
-build_message_expr (tree mess)
+objc_build_message_expr (tree mess)
 {
   tree receiver = TREE_PURPOSE (mess);
   tree sel_name;
@@ -5639,21 +5632,31 @@ build_message_expr (tree mess)
   return finish_message_expr (receiver, sel_name, method_params);
 }
 
+/* Look up method SEL_NAME that would be suitable for receiver
+   of type 'id' (if IS_CLASS is zero) or 'Class' (if IS_CLASS is
+   nonzero), and report on any duplicates.  */
+
 static tree
-lookup_method_in_hash_lists (tree sel_name)
+lookup_method_in_hash_lists (tree sel_name, int is_class)
 {
-  hash method_prototype = hash_lookup (nst_method_hash_list,
-                                      sel_name);
+  hash method_prototype = NULL;
+
+  if (!is_class)
+    method_prototype = hash_lookup (nst_method_hash_list,
+                                   sel_name);
                                        
   if (!method_prototype)
-    method_prototype = hash_lookup (cls_method_hash_list,
-                                   sel_name);
+    {
+      method_prototype = hash_lookup (cls_method_hash_list,
+                                     sel_name);
+      is_class = 1;
+    }
 
-  return check_duplicates (method_prototype, 1);
+  return check_duplicates (method_prototype, 1, is_class);
 }
 
 /* The 'finish_message_expr' routine is called from within
-   'build_message_expr' for non-template functions.  In the case of
+   'objc_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.  */
 
@@ -5661,7 +5664,7 @@ tree
 finish_message_expr (tree receiver, tree sel_name, tree method_params)
 {
   tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
-  tree selector, retval, is_class;
+  tree selector, retval, class_tree;
   int self, super, have_cast;
 
   /* Extract the receiver of the message, as well as its type
@@ -5682,14 +5685,14 @@ finish_message_expr (tree receiver, tree sel_name, tree method_params)
 
   /* If the receiver is a class object, retrieve the corresponding
      @interface, if one exists. */
-  is_class = receiver_is_class_object (receiver, self, super);
+  class_tree = receiver_is_class_object (receiver, self, super);
 
   /* Now determine the receiver type (if an explicit cast has not been
      provided).  */
   if (!have_cast)
     {
-      if (is_class)
-       rtype = lookup_interface (is_class);
+      if (class_tree)
+       rtype = lookup_interface (class_tree);
       /* Handle `self' and `super'.  */
       else if (super)
        {
@@ -5712,24 +5715,23 @@ finish_message_expr (tree receiver, tree sel_name, tree method_params)
        || TREE_TYPE (rtype) == TREE_TYPE (objc_class_type))
     {
       if (!rtype)
-       rtype = xref_tag (RECORD_TYPE, is_class);
+       rtype = xref_tag (RECORD_TYPE, class_tree);
       else if (IS_ID (rtype))
        {
          rprotos = TYPE_PROTOCOL_LIST (rtype);
          rtype = NULL_TREE;
        }
       else
-       is_class = TYPE_NAME (rtype) = get_identifier ("Class");
+       class_tree = TYPE_NAME (rtype) = get_identifier ("Class");
 
       if (rprotos)
        method_prototype
          = lookup_method_in_protocol_list (rprotos, sel_name,
-                                           is_class != NULL_TREE);
+                                           class_tree != NULL_TREE);
       if (!method_prototype && !rprotos)
        method_prototype
-         = (is_class
-            ? check_duplicates (hash_lookup (cls_method_hash_list, sel_name), 1)
-            : lookup_method_in_hash_lists (sel_name));
+         = lookup_method_in_hash_lists (sel_name,
+                                        class_tree != NULL_TREE);
     }
   else
     {
@@ -5761,7 +5763,7 @@ finish_message_expr (tree receiver, tree sel_name, tree method_params)
             in the published @interface for the class (and its
             superclasses). */
          method_prototype
-           = lookup_method_static (rtype, sel_name, is_class != NULL_TREE);
+           = lookup_method_static (rtype, sel_name, class_tree != NULL_TREE);
 
          /* If the method was not found in the @interface, it may still
             exist locally as part of the @implementation.  */
@@ -5770,7 +5772,7 @@ finish_message_expr (tree receiver, tree sel_name, tree method_params)
                == OBJC_TYPE_NAME (rtype))                      
            method_prototype
              = lookup_method
-               ((is_class
+               ((class_tree
                  ? CLASS_CLS_METHODS (objc_implementation_context)
                  : CLASS_NST_METHODS (objc_implementation_context)),
                  sel_name);
@@ -5780,7 +5782,7 @@ finish_message_expr (tree receiver, tree sel_name, tree method_params)
          if (!method_prototype && rprotos)
            method_prototype
              = lookup_method_in_protocol_list (rprotos, sel_name,
-                                               is_class != NULL_TREE);
+                                               class_tree != NULL_TREE);
        }
       else
        {
@@ -5797,11 +5799,11 @@ finish_message_expr (tree receiver, tree sel_name, tree method_params)
       if (rtype)
        warning ("`%s' may not respond to `%c%s'",
                 IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)),
-                (is_class ? '+' : '-'),
+                (class_tree ? '+' : '-'),
                 IDENTIFIER_POINTER (sel_name));
       if (rprotos)
        warning ("`%c%s' not implemented by protocol(s)",
-                (is_class ? '+' : '-'),
+                (class_tree ? '+' : '-'),
                 IDENTIFIER_POINTER (sel_name));
       if (!warn_missing_methods)
        {
@@ -5848,7 +5850,7 @@ build_objc_method_call (int super_flag, tree method_prototype,
                 (!flag_next_runtime || flag_nil_receivers
                  ? umsg_decl
                  : umsg_nonnil_decl));
-  tree rcv_p = (super_flag ? super_type : id_type);
+  tree rcv_p = (super_flag ? objc_super_type : objc_id_type);
 
   /* If a prototype for the method to be called exists, then cast
      the sender's return type and arguments to match that of the method.
@@ -5856,68 +5858,63 @@ build_objc_method_call (int super_flag, tree method_prototype,
   tree ret_type
     = (method_prototype
        ? groktypename (TREE_TYPE (method_prototype))
-       : id_type);
+       : objc_id_type);
   tree sender_cast
     = build_pointer_type
       (build_function_type
        (ret_type,
        get_arg_type_list
        (method_prototype, METHOD_REF, super_flag)));
+  tree method, t;
 
   lookup_object = build_c_cast (rcv_p, lookup_object);
+    
+  /* Use SAVE_EXPR to avoid evaluating the receiver twice.  */
+  lookup_object = save_expr (lookup_object);
 
   if (flag_next_runtime)
     {
-#ifdef STRUCT_VALUE
       /* If we are returning a struct in memory, and the address
         of that memory location is passed as a hidden first
         argument, then change which messenger entry point this
         expr will call.  NB: Note that sender_cast remains
         unchanged (it already has a struct return type).  */
-      if ((TREE_CODE (ret_type) == RECORD_TYPE
-          || TREE_CODE (ret_type) == UNION_TYPE)
-#if defined (DEFAULT_PCC_STRUCT_RETURN) && DEFAULT_PCC_STRUCT_RETURN == 0
-          && RETURN_IN_MEMORY (ret_type)
-#endif
-          && STRUCT_VALUE == 0)
+      if (!targetm.calls.struct_value_rtx (0, 0)
+         && (TREE_CODE (ret_type) == RECORD_TYPE
+             || TREE_CODE (ret_type) == UNION_TYPE)
+         && targetm.calls.return_in_memory (ret_type, 0))
        sender = (super_flag ? umsg_super_stret_decl :
                flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
-#endif
+
       method_params = tree_cons (NULL_TREE, lookup_object,
                                 tree_cons (NULL_TREE, selector,
                                            method_params));
-      TREE_USED (sender) = 1;
-      assemble_external (sender);
-      /* We want to cast the sender, not convert it.  */
-      return build_function_call (build_c_cast (sender_cast, sender),
-                                 method_params);
+      method = build_fold_addr_expr (sender);
     }
   else
     {
       /* This is the portable (GNU) way.  */
-      tree method, object;
+      tree object;
 
       /* First, call the lookup function to get a pointer to the method,
-        then cast the pointer, then call it with the method arguments.
-        Use SAVE_EXPR to avoid evaluating the receiver twice.  */
-      lookup_object = save_expr (lookup_object);
+        then cast the pointer, then call it with the method arguments.  */
+      
       object = (super_flag ? self_decl : lookup_object);
-      TREE_USED (sender) = 1;
-      assemble_external (sender);
-      method
-       = build_function_call (sender,
-                              tree_cons (NULL_TREE, lookup_object,
-                                         tree_cons (NULL_TREE, selector,
-                                                    NULL_TREE)));
+
+      t = tree_cons (NULL_TREE, selector, NULL_TREE);
+      t = tree_cons (NULL_TREE, lookup_object, t);
+      method = build_function_call (sender, t);
 
       /* Pass the object to the method.  */
-      TREE_USED (method) = 1;
-      assemble_external (method);
-      return build_function_call
-            (build_c_cast (sender_cast, method),
-             tree_cons (NULL_TREE, object,
-                        tree_cons (NULL_TREE, selector, method_params)));
+      method_params = tree_cons (NULL_TREE, object,
+                                tree_cons (NULL_TREE, selector,
+                                           method_params));
     }
+
+  /* ??? Selector is not at this point something we can use inside
+     the compiler itself.  Set it to garbage for the nonce.  */
+  t = build (OBJ_TYPE_REF, sender_cast, method, lookup_object, size_zero_node);
+  return build_function_call (t, method_params);
 }
 \f
 static void
@@ -5943,7 +5940,7 @@ build_protocol_reference (tree p)
       TREE_USED (decl) = 1;
       DECL_ARTIFICIAL (decl) = 1;
 
-      make_decl_rtl (decl, 0);
+      make_decl_rtl (decl);
       pushdecl_top_level (decl);
    }
 
@@ -5953,7 +5950,7 @@ build_protocol_reference (tree p)
 /* 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 (tree protoname)
+objc_build_protocol_expr (tree protoname)
 {
   tree expr;
   tree p = lookup_protocol (protoname);
@@ -5970,7 +5967,9 @@ build_protocol_expr (tree protoname)
 
   expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
 
-  TREE_TYPE (expr) = protocol_type;
+  /* ??? Ideally we'd build the reference with objc_protocol_type directly,
+     if we have it, rather than converting it here.  */
+  expr = convert (objc_protocol_type, expr);
 
   /* The @protocol() expression is being compiled into a pointer to a
      statically allocated instance of the Protocol class.  To become
@@ -5988,7 +5987,7 @@ build_protocol_expr (tree protoname)
   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
+        object.  (Cfr. objc_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));
@@ -6023,7 +6022,7 @@ build_protocol_expr (tree protoname)
    is found, in order to compile it.  It is only called by the parser
    and only to compile a @selector().  */
 tree
-build_selector_expr (tree selnamelist)
+objc_build_selector_expr (tree selnamelist)
 {
   tree selname;
 
@@ -6069,7 +6068,7 @@ build_selector_expr (tree selnamelist)
 }
 
 tree
-build_encode_expr (tree type)
+objc_build_encode_expr (tree type)
 {
   tree result;
   const char *string;
@@ -6101,7 +6100,7 @@ build_ivar_reference (tree id)
         paradigm.  */
       warning ("instance variable `%s' accessed in class method",
               IDENTIFIER_POINTER (id));
-      TREE_TYPE (self_decl) = instance_type; /* cast */
+      TREE_TYPE (self_decl) = objc_instance_type; /* cast */
     }
 
   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
@@ -6252,11 +6251,34 @@ lookup_method_static (tree interface, tree ident, int is_class)
   return is_class ? lookup_method_static (root_inter, ident, 0): NULL_TREE;
 }
 
+/* Add the method to the hash list if it doesn't contain an identical
+   method already. */
+static void
+add_method_to_hash_list (hash *hash_list, tree method)
+{
+  hash hsh;
+
+  if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
+    {
+      /* Install on a global chain.  */
+      hash_enter (hash_list, method);
+    }
+  else
+    {
+      /* Check types against those; if different, add to a list.  */
+      attr loop;
+      int already_there = comp_proto_with_proto (method, hsh->key);
+      for (loop = hsh->list; !already_there && loop; loop = loop->next)
+       already_there |= comp_proto_with_proto (method, loop->value);
+      if (!already_there)
+       hash_add_attr (hsh, method);
+    }
+}
+
 tree
-add_method (tree class, tree method, int is_class)
+objc_add_method (tree class, tree method, int is_class)
 {
   tree mth;
-  hash hsh;
 
   if (!(mth = lookup_method (is_class ? CLASS_CLS_METHODS (class) : CLASS_NST_METHODS (class), method)))
     {
@@ -6274,10 +6296,11 @@ add_method (tree class, tree method, int is_class)
     }
   else
     {
-      /* When processing an @interface for a class or category, give hard errors on methods with
-        identical selectors but differing argument and/or return types. We do not do this for
-        @implementations, because C/C++ will do it for us (i.e., there will be
-        duplicate function definition errors).  */
+      /* When processing an @interface for a class or category, give hard
+        errors on methods with identical selectors but differing argument
+        and/or return types. We do not do this for @implementations, because
+        C/C++ will do it for us (i.e., there will be duplicate function
+        definition errors).  */
       if ((TREE_CODE (class) == CLASS_INTERFACE_TYPE
           || TREE_CODE (class) == CATEGORY_INTERFACE_TYPE)
          && !comp_proto_with_proto (method, mth))
@@ -6285,23 +6308,23 @@ add_method (tree class, tree method, int is_class)
                is_class ? '+' : '-', IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
     }
 
-  if (!(hsh = hash_lookup (is_class
-                          ? cls_method_hash_list
-                          : nst_method_hash_list, METHOD_SEL_NAME (method))))
-    {
-      /* Install on a global chain.  */
-      hash_enter (is_class ? cls_method_hash_list : nst_method_hash_list, method);
-    }
+  if (is_class)
+    add_method_to_hash_list (cls_method_hash_list, method);
   else
     {
-      /* Check types against those; if different, add to a list.  */
-      attr loop;
-      int already_there = comp_proto_with_proto (method, hsh->key);
-      for (loop = hsh->list; !already_there && loop; loop = loop->next)
-       already_there |= comp_proto_with_proto (method, loop->value);
-      if (!already_there)
-       hash_add_attr (hsh, method);
+      add_method_to_hash_list (nst_method_hash_list, method);
+
+      /* Instance methods in root classes (and categories thereof)
+        may acts as class methods as a last resort. */
+      if (TREE_CODE (class) == CATEGORY_INTERFACE_TYPE
+         || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
+       class = lookup_interface (CLASS_NAME (class));
+
+      if (TREE_CODE (class) != PROTOCOL_INTERFACE_TYPE
+         && !CLASS_SUPER_NAME (class))
+       add_method_to_hash_list (cls_method_hash_list, method);
     }
+
   return method;
 }
 
@@ -6318,23 +6341,19 @@ static void
 add_category (tree class, tree category)
 {
   /* Put categories on list in reverse order.  */
-  tree cat = CLASS_CATEGORY_LIST (class);
+  tree cat = lookup_category (class, CLASS_SUPER_NAME (category));
 
-  while (cat)
+  if (cat)
     {
-      if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category))
-#ifdef OBJCPLUS
-       error ("duplicate interface declaration for category `%s(%s)'",
-#else  
-       warning ("duplicate interface declaration for category `%s(%s)'",
-#endif 
-                IDENTIFIER_POINTER (CLASS_NAME (class)),
-                IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
-      cat = CLASS_CATEGORY_LIST (cat);
+      warning ("duplicate interface declaration for category `%s(%s)'",
+              IDENTIFIER_POINTER (CLASS_NAME (class)),
+              IDENTIFIER_POINTER (CLASS_SUPER_NAME (category)));
+    }
+  else
+    {
+      CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
+      CLASS_CATEGORY_LIST (class) = category;
     }
-
-  CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
-  CLASS_CATEGORY_LIST (class) = category;
 }
 
 /* Called after parsing each instance variable declaration. Necessary to
@@ -6445,21 +6464,15 @@ is_ivar (tree decl_chain, tree ident)
 int
 is_private (tree decl)
 {
-  if (TREE_PRIVATE (decl)
-      && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl)))
-    {
-      error ("instance variable `%s' is declared private",
-            IDENTIFIER_POINTER (DECL_NAME (decl)));
-      return 1;
-    }
-  else
-    return 0;
+  return (TREE_PRIVATE (decl)
+         && ! is_ivar (CLASS_IVARS (implementation_template),
+                       DECL_NAME (decl)));
 }
 
 /* We have an instance variable reference;, check to see if it is public.  */
 
 int
-is_public (tree expr, tree identifier)
+objc_is_public (tree expr, tree identifier)
 {
   tree basetype = TREE_TYPE (expr);
   enum tree_code code = TREE_CODE (basetype);
@@ -6491,7 +6504,14 @@ is_public (tree expr, tree identifier)
                           == CATEGORY_IMPLEMENTATION_TYPE))
                      && (CLASS_NAME (objc_implementation_context)
                          == OBJC_TYPE_NAME (basetype))))
-               return ! is_private (decl);
+               {
+                 int private = is_private (decl);
+
+                 if (private)
+                   error ("instance variable `%s' is declared private",
+                          IDENTIFIER_POINTER (DECL_NAME (decl)));
+                 return !private;
+               }
 
              /* The 2.95.2 compiler sometimes allowed C functions to access
                 non-@public ivars.  We will let this slide for now...  */
@@ -6740,13 +6760,13 @@ start_class (enum tree_code code, tree class_name, tree super_name,
     }
 
   class = make_node (code);
-  TYPE_BINFO (class) = make_tree_vec (CLASS_BINFO_ELTS);
+  TYPE_LANG_SLOT_1 (class) = make_tree_vec (CLASS_LANG_SLOT_ELTS);
 
   CLASS_NAME (class) = class_name;
   CLASS_SUPER_NAME (class) = super_name;
   CLASS_CLS_METHODS (class) = NULL_TREE;
 
-  if (! is_class_name (class_name)
+  if (! objc_is_class_name (class_name)
       && (decl = lookup_name (class_name)))
     {
       error ("`%s' redeclared as different kind of symbol",
@@ -6952,15 +6972,7 @@ finish_class (tree class)
 
   else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE)
     {
-      tree category = CLASS_CATEGORY_LIST (implementation_template);
-
-      /* Find the category interface from the class it is associated with.  */
-      while (category)
-       {
-         if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
-           break;
-         category = CLASS_CATEGORY_LIST (category);
-       }
+      tree category = lookup_category (implementation_template, CLASS_SUPER_NAME (class));
 
       if (category)
        {
@@ -7037,7 +7049,8 @@ objc_declare_protocols (tree names)
        {
          tree protocol = make_node (PROTOCOL_INTERFACE_TYPE);
 
-         TYPE_BINFO (protocol) = make_tree_vec (2);
+         TYPE_LANG_SLOT_1 (protocol)
+           = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
          PROTOCOL_NAME (protocol) = name;
          PROTOCOL_LIST (protocol) = NULL_TREE;
          add_protocol (protocol);
@@ -7068,7 +7081,7 @@ start_protocol (enum tree_code code, tree name, tree list)
   if (!protocol)
     {
       protocol = make_node (code);
-      TYPE_BINFO (protocol) = make_tree_vec (2);
+      TYPE_LANG_SLOT_1 (protocol) = make_tree_vec (PROTOCOL_LANG_SLOT_ELTS);
 
       PROTOCOL_NAME (protocol) = name;
       PROTOCOL_LIST (protocol) = lookup_and_install_protocols (list);
@@ -7335,16 +7348,16 @@ encode_type (tree type, int curtype, int format)
     {
       switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
        {
-       case 8:  c = TREE_UNSIGNED (type) ? 'C' : 'c'; break;
-       case 16: c = TREE_UNSIGNED (type) ? 'S' : 's'; break;
+       case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
+       case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
        case 32: 
          if (type == long_unsigned_type_node
              || type == long_integer_type_node)
-                c = TREE_UNSIGNED (type) ? 'L' : 'l';
+                c = TYPE_UNSIGNED (type) ? 'L' : 'l';
          else
-                c = TREE_UNSIGNED (type) ? 'I' : 'i';
+                c = TYPE_UNSIGNED (type) ? 'I' : 'i';
          break;
-       case 64: c = TREE_UNSIGNED (type) ? 'Q' : 'q'; break;
+       case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
        default: abort ();
        }
       obstack_1grow (&util_obstack, c);
@@ -7498,9 +7511,7 @@ synth_self_and_ucmd_args (void)
                                    build1 (INDIRECT_REF, NULL_TREE, self_id)),
                   unused_list));
 
-  decl_specs = build_tree_list (NULL_TREE,
-                               xref_tag (RECORD_TYPE,
-                                         get_identifier (TAG_SELECTOR)));
+  decl_specs = build_tree_list (NULL_TREE, TREE_TYPE (objc_selector_type));
   push_parm_decl (build_tree_list
                  (build_tree_list (decl_specs,
                                    build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
@@ -7518,7 +7529,8 @@ start_method_def (tree method)
   UOBJC_SUPER_decl = NULL_TREE;
 
   /* Must be called BEFORE start_function.  */
-  pushlevel (0);
+  push_scope ();
+  declare_parm_level ();
 
   /* Generate prototype declarations for arguments..."new-style".  */
   synth_self_and_ucmd_args ();
@@ -7593,13 +7605,13 @@ comp_method_with_proto (tree method, tree proto)
     function1_template = make_node (FUNCTION_TYPE);
 
   /* Install argument types - normally set by build_function_type.  */
-  TYPE_ARG_TYPES (function1_template) = 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 (function1_template) = groktypename (TREE_TYPE (proto));
 
-  return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template,
-                   false);
+  return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function1_template);
 }
 
 /* Return 1 if TYPE1 is equivalent to TYPE2.  */
@@ -7754,12 +7766,34 @@ really_start_method (tree method, tree parmlist)
                                METHOD_SEL_NAME (method),
                                TREE_CODE (method) == CLASS_METHOD_DECL);
 
-      if (proto && ! comp_method_with_proto (method, proto))
+      if (proto)
        {
-         char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
+         if (!comp_method_with_proto (method, proto))
+           {
+             char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+');
 
-         warn_with_method ("conflicting types for", type, method);
-         warn_with_method ("previous declaration of", type, proto);
+             warn_with_method ("conflicting types for", type, method);
+             warn_with_method ("previous declaration of", type, proto);
+           }
+       }
+      else
+       {
+         /* We have a method @implementation even though we did not
+            see a corresponding @interface declaration (which is allowed
+            by Objective-C rules).  Go ahead and place the method in
+            the @interface anyway, so that message dispatch lookups
+            will see it.  */
+         tree interface = implementation_template;
+
+         if (TREE_CODE (objc_implementation_context)
+             == CATEGORY_IMPLEMENTATION_TYPE)
+           interface = lookup_category
+                       (interface,
+                        CLASS_SUPER_NAME (objc_implementation_context));
+
+         if (interface)
+           objc_add_method (interface, copy_node (method),
+                            TREE_CODE (method) == CLASS_METHOD_DECL);
        }
     }
 }
@@ -7776,9 +7810,9 @@ continue_method_def (void)
 
   if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
     /* We have a `, ...' immediately following the selector.  */
-    parmlist = get_parm_info (0);
+    parmlist = get_parm_info (/*ellipsis=*/true);
   else
-    parmlist = get_parm_info (1); /* place a `void_at_end' */
+    parmlist = get_parm_info (/*ellipsis=*/false);
 
 #ifndef OBJCPLUS
   /* Set self_decl from the first argument...this global is used by
@@ -7786,7 +7820,7 @@ continue_method_def (void)
   self_decl = TREE_PURPOSE (parmlist);
 #endif /* !OBJCPLUS */
 
-  poplevel (0, 0, 0);
+  pop_scope ();
   really_start_method (objc_method_context, parmlist);
   store_parm_decls ();
 }
@@ -7819,17 +7853,22 @@ get_super_receiver (void)
        TREE_USED (UOBJC_SUPER_decl) = 1;
        DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1;
 
-       UOBJC_SUPER_scope = get_current_scope ();
+       UOBJC_SUPER_scope = objc_get_current_scope ();
       }
 
       /* Set receiver to self.  */
       super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
-      super_expr_list = build_tree_list (NULL_TREE, super_expr);
+      super_expr_list = super_expr;
 
       /* Set class to begin searching.  */
+#ifdef OBJCPLUS
+      super_expr = build_component_ref (UOBJC_SUPER_decl,
+                                       get_identifier ("super_class"));
+#else
       super_expr = build_component_ref (UOBJC_SUPER_decl,
                                        get_identifier ("class"));
+#endif
 
       if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
        {
@@ -7859,7 +7898,7 @@ get_super_receiver (void)
 
          if (flag_next_runtime && !flag_zero_link)
            {
-             super_class = get_class_reference (super_name);
+             super_class = objc_get_class_reference (super_name);
              if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
                /* If we are in a class method, we must retrieve the
                   _metaclass_ for the current class, pointed at by
@@ -7891,12 +7930,12 @@ get_super_receiver (void)
                                               super_class));
        }
 
-      chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
+      super_expr_list = build_compound_expr (super_expr_list, super_expr);
 
       super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
-      chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
+      super_expr_list = build_compound_expr (super_expr_list, super_expr);
 
-      return build_compound_expr (super_expr_list);
+      return super_expr_list;
     }
   else
     {
@@ -7912,7 +7951,7 @@ void
 objc_clear_super_receiver (void)
 {
   if (objc_method_context
-      && UOBJC_SUPER_scope == get_current_scope ()) {
+      && UOBJC_SUPER_scope == objc_get_current_scope ()) {
     UOBJC_SUPER_decl = 0;
     UOBJC_SUPER_scope = 0;
   }
@@ -7941,7 +7980,6 @@ finish_method_def (void)
      dispatched, so suppress all thoughts of doing so.  */
   DECL_INLINE (current_function_decl) = 0;
   DECL_UNINLINABLE (current_function_decl) = 1;
-  current_function_cannot_inline = "methods cannot be inlined";
 
   finish_function ();
   lang_expand_function_end = NULL;
@@ -8066,9 +8104,9 @@ adorn_decl (tree decl, char *str)
   else if (code == POINTER_TYPE)
     {
       strcpy (tmpbuf, "*");
-      if (TREE_READONLY (decl) || TYPE_VOLATILE (decl))
+      if (TYPE_READONLY (decl) || TYPE_VOLATILE (decl))
        {
-         if (TREE_READONLY (decl))
+         if (TYPE_READONLY (decl))
            strcat (tmpbuf, " const");
          if (TYPE_VOLATILE (decl))
            strcat (tmpbuf, " volatile");
@@ -8272,7 +8310,7 @@ gen_declspecs (tree declspecs, char *buf, int raw)
   else
     {
       /* Type qualifiers.  */
-      if (TREE_READONLY (declspecs))
+      if (TYPE_READONLY (declspecs))
        strcat (buf, "const ");
       if (TYPE_VOLATILE (declspecs))
        strcat (buf, "volatile ");
@@ -8753,8 +8791,6 @@ finish_objc (void)
       objc_implementation_context = NULL_TREE;
     }
 
-  generate_forward_declaration_to_string_table ();
-
   /* Process the static instances here because initialization of objc_symtab
      depends on them.  */
   if (objc_static_instances)
@@ -8845,9 +8881,9 @@ finish_objc (void)
       for (slot = 0; slot < SIZEHASHTABLE; slot++)
        {
          for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
-           check_duplicates (hsh, 0);
+           check_duplicates (hsh, 0, 1);
          for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
-           check_duplicates (hsh, 0);
+           check_duplicates (hsh, 0, 1);
        }
     }
 
@@ -8907,7 +8943,7 @@ handle_class_ref (tree chain)
   TREE_PUBLIC (decl) = 1;
 
   pushdecl (decl);
-  rest_of_decl_compilation (decl, 0, 0, 0);
+  rest_of_decl_compilation (decl, 0, 0);
 
   /* Make a decl for the address.  */
   sprintf (string, "%sobjc_class_ref_%s",
@@ -8919,7 +8955,7 @@ handle_class_ref (tree chain)
   TREE_USED (decl) = 1;
 
   pushdecl (decl);
-  rest_of_decl_compilation (decl, 0, 0, 0);
+  rest_of_decl_compilation (decl, 0, 0);
 }
 
 static void
@@ -8970,8 +9006,7 @@ handle_impent (struct imp_entry *impent)
     {
       tree decl, init;
 
-      init = build_int_2 (0, 0);
-      TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
+      init = build_int_cst (c_common_type_for_size (BITS_PER_WORD, 1), 0);
       decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
       TREE_PUBLIC (decl) = 1;
       TREE_READONLY (decl) = 1;
@@ -8984,7 +9019,7 @@ handle_impent (struct imp_entry *impent)
     }
 }
 \f
-/* The Fix-and-Countinue functionality available in Mac OS X 10.3 and
+/* The Fix-and-Continue functionality available in Mac OS X 10.3 and
    later requires that ObjC translation units participating in F&C be
    specially marked.  The following routine accomplishes this.  */
 
@@ -9001,13 +9036,13 @@ generate_objc_image_info (void)
                 tree_cons (NULL_TREE,
                            build_array_type
                            (integer_type_node,
-                            build_index_type (build_int_2 (1, 0))),
+                            build_index_type (build_int_cst (NULL_TREE, 1))),
                            sc_spec),
                 1,
                 NULL_TREE);
 
-  initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0));
-  initlist = tree_cons (NULL_TREE, build_int_2 (1, 0), initlist);
+  initlist = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, 0));
+  initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 1), initlist);
   initlist = build_constructor (TREE_TYPE (decl), nreverse (initlist));
 
   TREE_USED (decl) = DECL_IGNORED_P (decl) = DECL_ARTIFICIAL (decl) = 1;
@@ -9018,7 +9053,7 @@ generate_objc_image_info (void)
 /* Look up ID as an instance variable.  */
 
 tree
-lookup_objc_ivar (tree id)
+objc_lookup_ivar (tree id)
 {
   tree decl;
 
@@ -9028,7 +9063,7 @@ lookup_objc_ivar (tree id)
   else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
     {
       if (is_private (decl))
-       return error_mark_node;
+       return 0;
       else
         return build_ivar_reference (id);
     }
@@ -9037,4 +9072,3 @@ lookup_objc_ivar (tree id)
 }
 
 #include "gt-objc-objc-act.h"
-#include "gtype-objc.h"