OSDN Git Service

* c-typeck.c (comptypes, tagged_types_tu_compatible_p,
[pf3gnuchains/gcc-fork.git] / gcc / objc / objc-act.c
index 40c7004..96e29b1 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.
@@ -45,10 +45,12 @@ Boston, MA 02111-1307, USA.  */
 #include "tm.h"
 #include "tree.h"
 #include "rtl.h"
+#include "tm_p.h"
 #include "expr.h"
 #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 +64,6 @@ Boston, MA 02111-1307, USA.  */
 #include "diagnostic.h"
 #include "cgraph.h"
 
-#define OBJC_VOID_AT_END       build_tree_list (NULL_TREE, void_type_node)
-
 /* This is the default way of generating a method name.  */
 /* I am not sure it is really correct.
    Perhaps there's a danger that it will make name conflicts
@@ -148,7 +148,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);
@@ -159,7 +159,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);
@@ -183,8 +182,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
 {
@@ -279,7 +280,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);
@@ -903,6 +904,11 @@ objc_comptypes (tree lhs, tree rhs, int reflexive)
               && OBJC_TYPE_NAME (rhs) == objc_object_id))
     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))
@@ -944,10 +950,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 (TYPE_NAME (type) && (type = is_class_name (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.  */
@@ -1156,124 +1161,107 @@ synth_module_prologue (void)
 
   /* 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 *' */
+    selector_type
+      = build_pointer_type (xref_tag (RECORD_TYPE,
+                                     get_identifier (TAG_SELECTOR)));
+  else
+    /* `const struct objc_selector *' */
+    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, ...); */
-
-  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 (id_type,
+                              tree_cons (NULL_TREE, id_type,
+                                         tree_cons (NULL_TREE, 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
+      /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
+      /* id objc_msgSendSuper_stret (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);
       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 (id_type,      
+                               tree_cons (NULL_TREE, id_type,      
+                                          tree_cons (NULL_TREE, selector_type,      
+                                                     NULL_TREE))));      
+
+      /* IMP objc_msg_lookup (id, SEL); */
+      temp_type
+        = build_function_type (IMP_type,
+                               tree_cons (NULL_TREE, id_type,
+                                          tree_cons (NULL_TREE, 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, super_type,
+                                          tree_cons (NULL_TREE, 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,
                                   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,
@@ -1319,8 +1307,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;
@@ -1395,6 +1381,7 @@ build_objc_string_object (tree string)
 {
   tree initlist, constructor, constant_string_class;
   int length;
+  tree fields;
 
   string = fix_string_type (string);
 
@@ -1424,6 +1411,7 @@ build_objc_string_object (tree string)
        }
       add_class_reference (constant_string_id);
     }
+  fields = TYPE_FIELDS (constant_string_type);
 
   /* & ((NXConstantString) { NULL, string, length })  */
 
@@ -1439,18 +1427,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_2 (0, 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_2 (length, 0), initlist);
   constructor = objc_build_constructor (constant_string_type,
                                        nreverse (initlist));
 
@@ -1891,7 +1884,7 @@ 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;
@@ -1906,7 +1899,7 @@ 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 ();
@@ -1933,22 +1926,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
@@ -2713,7 +2690,7 @@ objc_enter_block (void)
   block = begin_compound_stmt (0);
 #else
   block = c_begin_compound_stmt ();
-  pushlevel (0);
+  push_scope ();
   clear_last_expr ();
   add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
 #endif
@@ -2738,7 +2715,7 @@ objc_exit_block (void)
   finish_compound_stmt (0, block);
 #else
   scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
-  inner = poplevel (KEEP_MAYBE, 1, 0);
+  inner = pop_scope ();
 
   SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
        = SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
@@ -2848,8 +2825,7 @@ objc_build_try_enter_fragment (void)
   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);
+  c_expand_start_cond (lang_hooks.truthvalue_conversion (cond), 0, if_stmt);
   objc_enter_block ();
 }
 
@@ -2976,7 +2952,7 @@ objc_build_try_epilogue (int also_catch_prologue)
       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),
+      c_expand_start_cond (lang_hooks.truthvalue_conversion (boolean_false_node),
                           0, if_stmt);
       objc_enter_block ();
 
@@ -3066,8 +3042,7 @@ objc_build_catch_stmt (tree catch_expr)
       cond = build_function_call (objc_exception_match_decl, func_params);
     }
 
-  c_expand_start_cond (c_common_truthvalue_conversion (cond),
-                      0, if_stmt);
+  c_expand_start_cond (lang_hooks.truthvalue_conversion (cond), 0, if_stmt);
   objc_enter_block ();
   objc_declare_variable (RID_REGISTER, var_name,
                         build_pointer_type (var_type),
@@ -3124,7 +3099,7 @@ objc_build_catch_epilogue (void)
 }
 
 tree
-objc_build_finally_prologue ()
+objc_build_finally_prologue (void)
 {
   /* { // begin FINALLY scope
        if (!_rethrowException) {
@@ -3136,10 +3111,10 @@ objc_build_finally_prologue ()
   tree if_stmt = c_begin_if_stmt ();
   if_nesting_count++;
 
-  c_expand_start_cond (c_common_truthvalue_conversion
-                      (build_unary_op
-                       (TRUTH_NOT_EXPR,
-                        TREE_VALUE (objc_rethrow_exception), 0)),
+  c_expand_start_cond (lang_hooks.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 ();
@@ -3164,7 +3139,7 @@ objc_build_finally_epilogue (void)
   if_nesting_count++;
 
   c_expand_start_cond
-    (c_common_truthvalue_conversion (TREE_VALUE (objc_rethrow_exception)),
+    (lang_hooks.truthvalue_conversion (TREE_VALUE (objc_rethrow_exception)),
      0, if_stmt);
   objc_enter_block ();
   objc_build_throw_stmt (TREE_VALUE (objc_rethrow_exception));
@@ -3334,7 +3309,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
@@ -3345,7 +3320,7 @@ build_objc_exception_stuff (void)
     = build_function_type (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 *); */
@@ -3354,7 +3329,7 @@ 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
@@ -3364,7 +3339,7 @@ build_objc_exception_stuff (void)
   /* void objc_sync_exit(id); */
   temp_type = build_function_type (void_type_node,
                                   tree_cons (NULL_TREE, id_type,
-                                             OBJC_VOID_AT_END));
+                                             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)
@@ -3377,7 +3352,7 @@ build_objc_exception_stuff (void)
   temp_type = build_function_type (integer_type_node,
                                   tree_cons (NULL_TREE, id_type,
                                              tree_cons (NULL_TREE, id_type,
-                                                        OBJC_VOID_AT_END)));
+                                                        void_list_node)));
   objc_exception_match_decl
     = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
        
@@ -4282,7 +4257,7 @@ check_ivars (tree inter, tree imp)
 
       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
 
-      if (!comptypes (t1, t2, false)
+      if (!comptypes (t1, t2)
          || !tree_int_cst_equal (TREE_VALUE (TREE_VALUE (rawintdecls)),
                                  TREE_VALUE (TREE_VALUE (rawimpdecls))))
        {
@@ -4341,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);
@@ -4555,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;
 
@@ -5064,6 +5046,18 @@ build_shared_structure_initializer (tree type, tree isa, tree super,
   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
@@ -5078,15 +5072,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))
     {
@@ -5465,7 +5452,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))
     {
@@ -5474,14 +5461,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;
 
@@ -5494,15 +5481,23 @@ 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;
@@ -5546,7 +5541,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)
@@ -5638,17 +5633,27 @@ 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
@@ -5726,9 +5731,8 @@ finish_message_expr (tree receiver, tree sel_name, tree method_params)
                                            is_class != 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,
+                                        is_class != NULL_TREE);
     }
   else
     {
@@ -5867,21 +5871,18 @@ build_objc_method_call (int super_flag, tree method_prototype,
 
   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));
@@ -5969,7 +5970,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 protocol_type directly,
+     if we have it, rather than converting it here.  */
+  expr = convert (protocol_type, expr);
 
   /* The @protocol() expression is being compiled into a pointer to a
      statically allocated instance of the Protocol class.  To become
@@ -6251,11 +6254,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)))
     {
@@ -6273,10 +6299,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))
@@ -6284,23 +6311,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;
 }
 
@@ -6317,23 +6344,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
@@ -6444,21 +6467,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);
@@ -6490,7 +6507,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...  */
@@ -6951,15 +6975,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)
        {
@@ -7324,62 +7340,42 @@ encode_next_bitfield (int width)
 }
 \f
 /* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS.  */
-
 static void
 encode_type (tree type, int curtype, int format)
 {
   enum tree_code code = TREE_CODE (type);
+  char c;
 
   if (code == INTEGER_TYPE)
     {
-      if (integer_zerop (TYPE_MIN_VALUE (type)))
+      switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
        {
-         /* Unsigned integer types.  */
-
-         if (TYPE_MODE (type) == QImode)
-           obstack_1grow (&util_obstack, 'C');
-         else if (TYPE_MODE (type) == HImode)
-           obstack_1grow (&util_obstack, 'S');
-         else if (TYPE_MODE (type) == SImode)
-           {
-             if (type == long_unsigned_type_node)
-               obstack_1grow (&util_obstack, 'L');
-             else
-               obstack_1grow (&util_obstack, 'I');
-           }
-         else if (TYPE_MODE (type) == DImode)
-           obstack_1grow (&util_obstack, 'Q');
-       }
-
-      else
-       /* Signed integer types.  */
-       {
-         if (TYPE_MODE (type) == QImode)
-           obstack_1grow (&util_obstack, 'c');
-         else if (TYPE_MODE (type) == HImode)
-           obstack_1grow (&util_obstack, 's');
-         else if (TYPE_MODE (type) == SImode)
-           {
-             if (type == long_integer_type_node)
-               obstack_1grow (&util_obstack, 'l');
-             else
-               obstack_1grow (&util_obstack, 'i');
-           }
-
-         else if (TYPE_MODE (type) == DImode)
-           obstack_1grow (&util_obstack, 'q');
+       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 = TYPE_UNSIGNED (type) ? 'L' : 'l';
+         else
+                c = TYPE_UNSIGNED (type) ? 'I' : 'i';
+         break;
+       case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
+       default: abort ();
        }
+      obstack_1grow (&util_obstack, c);
     }
 
   else if (code == REAL_TYPE)
     {
       /* Floating point types.  */
-
-      if (TYPE_MODE (type) == SFmode)
-       obstack_1grow (&util_obstack, 'f');
-      else if (TYPE_MODE (type) == DFmode
-              || TYPE_MODE (type) == TFmode)
-       obstack_1grow (&util_obstack, 'd');
+      switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+       {
+       case 32:  c = 'f'; break;
+       case 64:
+       case 128: c = 'd'; break;
+       default: abort ();
+       }
+      obstack_1grow (&util_obstack, c);
     }
 
   else if (code == VOID_TYPE)
@@ -7517,9 +7513,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 (selector_type));
   push_parm_decl (build_tree_list
                  (build_tree_list (decl_specs,
                                    build1 (INDIRECT_REF, NULL_TREE, ucmd_id)),
@@ -7537,7 +7531,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 ();
@@ -7617,8 +7612,7 @@ comp_method_with_proto (tree method, tree proto)
   /* 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.  */
@@ -7773,12 +7767,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);
        }
     }
 }
@@ -7795,9 +7811,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
@@ -7805,7 +7821,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 ();
 }
@@ -7847,8 +7863,13 @@ get_super_receiver (void)
       super_expr_list = build_tree_list (NULL_TREE, 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)
        {
@@ -8085,9 +8106,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");
@@ -8291,7 +8312,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 ");
@@ -8480,7 +8501,8 @@ gen_declaration_1 (tree atype_or_adecl, char *buf)
          strcat (buf, gen_declarator (declarator, declbuf, ""));
        }
       if (width)
-       sprintf (buf + strlen (buf), ": %lu", TREE_INT_CST_LOW (width));
+       sprintf (buf + strlen (buf), ": " HOST_WIDE_INT_PRINT_UNSIGNED, 
+                TREE_INT_CST_LOW (width));
     }
 
   else
@@ -8771,8 +8793,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)
@@ -8863,9 +8883,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);
        }
     }
 
@@ -9002,7 +9022,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.  */
 
@@ -9046,7 +9066,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);
     }