Index: gcc/objc/ChangeLog
===================================================================
--- gcc/objc/ChangeLog  (revision 179864)
+++ gcc/objc/ChangeLog  (working copy)
@@ -1,3 +1,54 @@
+2011-10-14  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * objc-map.h: New file.
+       * objc-map.c: New file. 
+       * config-lang.in (gtfiles): Added objc-map.h.
+       * Make-lang.in (OBJC_OBJS): Added objc-map.o.
+       (objc/objc-map.o): New rule.
+       (objc/objc-act.o): Depend on objc/objc-map.h.
+       * objc-next-runtime-abi-02.c: Added a TODO comment.
+       * objc-act.c: Include objc-map.h.
+       (nst_method_hash_list, cls_method_hash_list): Removed.
+       (instance_method_map, class_method_map): New.
+       (cls_name_hash_list, als_name_hash_list): Removed.
+       (class_name_map, alias_name_map): Removed.
+       (ivar_offset_hash_list): Removed.
+       (hash_class_name_enter, hash_class_name_lookup, hash_enter,
+       hash_lookup, hash_add_attr, add_method_to_hash_list): Removed.
+       (interface_hash_init): New.
+       (objc_init): Call interface_hash_init.
+       (objc_write_global_declarations): Iterate over class_method_map
+       and instance_method_map instead of cls_method_hash_list and
+       nst_method_hash_list.
+       (objc_declare_alias): Use alias_name_map instead of
+       cls_name_hash_list.
+       (objc_is_class_name): Use class_name_map and alias_name_map
+       instead of cls_name_hash_list and als_name_hash_list.
+       (interface_tuple, interface_htab, hash_interface, eq_interface):
+       Removed.
+       (interface_map): New.
+       (add_class): Renamed to add_interface.  Use interface_map instead
+       of interface_htab.
+       (lookup_interface): Use interface_map instead of interface_htab.
+       (check_duplicates): Changed first argument to be a tree,
+       potentially a TREE_VEC, instead of a hash.  Changed implementation
+       to match.
+       (lookup_method_in_hash_lists): Use class_method_map and
+       instance_method_map instead of cls_method_hash_list and
+       nst_method_hash_list.
+       (objc_build_selector_expr): Likewise.
+       (hash_func): Removed.
+       (hash_init): Create instance_method_map, class_method_map,
+       class_name_map, and alias_name_map.  Do not create
+       nst_method_hash_list, cls_method_hash_list, cls_name_hash_list,
+       als_name_hash_list, and ivar_offset_hash_list.
+       (insert_method_into_method_map): New.
+       (objc_add_method): Use insert_method_into_method_map instead of
+       add_method_to_hash_list.
+       (start_class): Call add_interface instead of add_class.
+       * objc-act.h (cls_name_hash_list, als_name_hash_list,
+       nst_method_hash_list, cls_method_hash_list): Removed.
+
 2011-10-11  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        * objc-next-runtime-abi-01.c (objc_build_exc_ptr): Delete old
Index: gcc/objc/config-lang.in
===================================================================
--- gcc/objc/config-lang.in     (revision 179864)
+++ gcc/objc/config-lang.in     (working copy)
@@ -36,4 +36,4 @@ lang_requires="c"
 # Order is important.  If you change this list, make sure you test
 # building without C++ as well; that is, remove the gcc/cp directory,
 # and build with --enable-languages=c,objc.
-gtfiles="\$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-lang.h \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
+gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-lang.h \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
Index: gcc/objc/Make-lang.in
===================================================================
--- gcc/objc/Make-lang.in       (revision 179864)
+++ gcc/objc/Make-lang.in       (working copy)
@@ -55,7 +55,8 @@ OBJC_OBJS = objc/objc-lang.o objc/objc-act.o \
    objc/objc-gnu-runtime-abi-01.o \
    objc/objc-next-runtime-abi-01.o \
    objc/objc-next-runtime-abi-02.o \
-   objc/objc-encoding.o
+   objc/objc-encoding.o \
+   objc/objc-map.o
 
 objc_OBJS = $(OBJC_OBJS) cc1obj-checksum.o
 
@@ -129,6 +130,7 @@ objc/objc-act.o : objc/objc-act.c \
    $(HASHTAB_H) $(GIMPLE_H) \
    $(C_PRAGMA_H) $(C_TARGET_H) \
    objc/objc-encoding.h \
+   objc/objc-map.h \
    objc/objc-runtime-hooks.h \
    objc/objc-runtime-shared-support.h
 
@@ -139,6 +141,12 @@ objc/objc-encoding.o : objc/objc-encoding.c \
    objc/objc-encoding.h \
    objc/objc-runtime-shared-support.h
 
+objc/objc-map.o : objc/objc-map.c \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   objc/objc-map.h
+
 objc.srcextra:
 
 #^L
Index: gcc/objc/objc-next-runtime-abi-02.c
===================================================================
--- gcc/objc/objc-next-runtime-abi-02.c (revision 179864)
+++ gcc/objc/objc-next-runtime-abi-02.c (working copy)
@@ -231,6 +231,7 @@ static tree begin_catch (struct objc_try_context *
 static void finish_catch (struct objc_try_context **, tree);
 static tree finish_try_stmt (struct objc_try_context **);
 
+/* TODO: Use an objc-map.  */
 static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
 
 bool
Index: gcc/objc/objc-act.c
===================================================================
--- gcc/objc/objc-act.c (revision 179864)
+++ gcc/objc/objc-act.c (working copy)
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "langhooks.h"
 #include "objc-act.h"
+#include "objc-map.h"
 #include "input.h"
 #include "function.h"
 #include "output.h"
@@ -157,27 +158,25 @@ static void objc_generate_cxx_cdtors (void);
 static void objc_decl_method_attributes (tree*, tree, int);
 static tree build_keyword_selector (tree);
 
-/* Hash tables to manage the global pool of method prototypes.  */
 static void hash_init (void);
 
-hash *nst_method_hash_list = 0;
-hash *cls_method_hash_list = 0;
+/* Hash tables to manage the global pool of method prototypes.  Each
+   of these maps map a method name (selector) identifier to either a
+   single tree (for methods with a single method prototype) or a
+   TREE_VEC (for methods with multiple method prototypes).  */
+static GTY(()) objc_map_t instance_method_map = 0;
+static GTY(()) objc_map_t class_method_map = 0;
 
 /* Hash tables to manage the global pool of class names.  */
 
-hash *cls_name_hash_list = 0;
-hash *als_name_hash_list = 0;
+static GTY(()) objc_map_t class_name_map = 0;
+static GTY(()) objc_map_t alias_name_map = 0;
 
-hash *ivar_offset_hash_list = 0;
-
-static void hash_class_name_enter (hash *, tree, tree);
-static hash hash_class_name_lookup (hash *, tree);
-
-static hash hash_lookup (hash *, tree);
 static tree lookup_method (tree, tree);
 static tree lookup_method_static (tree, tree, int);
 
-static tree add_class (tree, tree);
+static void interface_hash_init (void);
+static tree add_interface (tree, tree);
 static void add_category (tree, tree);
 static inline tree lookup_category (tree, tree);
 
@@ -207,7 +206,7 @@ static void generate_struct_by_value_array (void)
 
 static void mark_referenced_methods (void);
 static bool objc_type_valid_for_messaging (tree type, bool allow_classes);
-static tree check_duplicates (hash, int, int);
+static tree check_duplicates (tree, int, int);
 
 /*** Private Interface (data) ***/
 /* Flags for lookup_method_static().  */
@@ -380,6 +379,7 @@ objc_init (void)
 
   /* Set up stuff used by FE parser and all runtimes.  */
   errbuf = XNEWVEC (char, 1024 * 10);
+  interface_hash_init ();
   hash_init ();
   objc_encoding_init ();
   /* ... and then check flags and set-up for the selected runtime ... */
@@ -418,19 +418,15 @@ objc_write_global_declarations (void)
 
   if (warn_selector)
     {
-      int slot;
-      hash hsh;
+      objc_map_iterator_t i;
 
-      /* Run through the selector hash tables and print a warning for any
-         selector which has multiple methods.  */
+      objc_map_iterator_initialize (class_method_map, &i);
+      while (objc_map_iterator_move_to_next (class_method_map, &i))
+       check_duplicates (objc_map_iterator_current_value (class_method_map, i), 0, 1);
 
-      for (slot = 0; slot < SIZEHASHTABLE; slot++)
-       {
-         for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
-           check_duplicates (hsh, 0, 1);
-         for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
-           check_duplicates (hsh, 0, 0);
-       }
+      objc_map_iterator_initialize (instance_method_map, &i);
+      while (objc_map_iterator_move_to_next (instance_method_map, &i))
+       check_duplicates (objc_map_iterator_current_value (instance_method_map, i), 0, 0);
     }
 
   /* TODO: consider an early exit here if either errorcount or sorrycount
@@ -3351,8 +3347,7 @@ objc_declare_alias (tree alias_ident, tree class_i
 #ifdef OBJCPLUS
       pop_lang_context ();
 #endif
-      hash_class_name_enter (als_name_hash_list, alias_ident,
-                            underlying_class);
+      objc_map_put (alias_name_map, alias_ident, underlying_class);
     }
 }
 
@@ -3392,15 +3387,13 @@ objc_declare_class (tree identifier)
         the TYPE_OBJC_INTERFACE.  If later an @interface is found,
         we'll replace the ident with the interface.  */
       TYPE_OBJC_INTERFACE (record) = identifier;
-      hash_class_name_enter (cls_name_hash_list, identifier, NULL_TREE);
+      objc_map_put (class_name_map, identifier, NULL_TREE);
     }
 }
 
 tree
 objc_is_class_name (tree ident)
 {
-  hash target;
-
   if (ident && TREE_CODE (ident) == IDENTIFIER_NODE)
     {
       tree t = identifier_global_value (ident);
@@ -3428,17 +3421,18 @@ objc_is_class_name (tree ident)
   if (lookup_interface (ident))
     return ident;
 
-  target = hash_class_name_lookup (cls_name_hash_list, ident);
-  if (target)
-    return target->key;
+  {
+    tree target;
 
-  target = hash_class_name_lookup (als_name_hash_list, ident);
-  if (target)
-    {
-      gcc_assert (target->list && target->list->value);
-      return target->list->value;
-    }
+    target = objc_map_get (class_name_map, ident);
+    if (target != OBJC_MAP_NOT_FOUND)
+      return ident;
 
+    target = objc_map_get (alias_name_map, ident);
+    if (target != OBJC_MAP_NOT_FOUND)
+      return target;
+  }
+
   return 0;
 }
 
@@ -3761,25 +3755,30 @@ objc_generate_write_barrier (tree lhs, enum tree_c
   return result;
 }
 
-struct GTY(()) interface_tuple {
-  tree id;
-  tree class_name;
-};
+/* Implementation of the table mapping a class name (as an identifier)
+   to a class node.  The two public functions for it are
+   lookup_interface() and add_interface().  add_interface() is only
+   used in this file, so we can make it static.  */
 
-static GTY ((param_is (struct interface_tuple))) htab_t interface_htab;
+static GTY(()) objc_map_t interface_map;
 
-static hashval_t
-hash_interface (const void *p)
+static void
+interface_hash_init (void)
 {
-  const struct interface_tuple *d = (const struct interface_tuple *) p;
-  return IDENTIFIER_HASH_VALUE (d->id);
+  interface_map = objc_map_alloc_ggc (200);  
 }
 
-static int
-eq_interface (const void *p1, const void *p2)
+static tree
+add_interface (tree class_name, tree name)
 {
-  const struct interface_tuple *d = (const struct interface_tuple *) p1;
-  return d->id == p2;
+  /* Put interfaces on list in reverse order.  */
+  TREE_CHAIN (class_name) = interface_chain;
+  interface_chain = class_name;
+
+  /* Add it to the map.  */
+  objc_map_put (interface_map, name, class_name);
+
+  return interface_chain;
 }
 
 tree
@@ -3794,19 +3793,12 @@ lookup_interface (tree ident)
     return NULL_TREE;
 
   {
-    struct interface_tuple **slot;
-    tree i = NULL_TREE;
+    tree interface = objc_map_get (interface_map, ident);
 
-    if (interface_htab)
-      {
-       slot = (struct interface_tuple **)
-         htab_find_slot_with_hash (interface_htab, ident,
-                                   IDENTIFIER_HASH_VALUE (ident),
-                                   NO_INSERT);
-       if (slot && *slot)
-         i = (*slot)->class_name;
-      }
-    return i;
+    if (interface == OBJC_MAP_NOT_FOUND)
+      return NULL_TREE;
+    else
+      return interface;
   }
 }
 
@@ -5052,71 +5044,75 @@ build_function_type_for_method (tree return_type,
   return ftype;
 }
 
+/* The 'method' argument is a tree; this tree could either be a single
+   method, which is returned, or could be a TREE_VEC containing a list
+   of methods.  In that case, the first one is returned, and warnings
+   are issued as appropriate.  */
 static tree
-check_duplicates (hash hsh, int methods, int is_class)
+check_duplicates (tree method, int methods, int is_class)
 {
-  tree meth = NULL_TREE;
+  tree first_method;
+  size_t i;
 
-  if (hsh)
-    {
-      meth = hsh->key;
+  if (method == NULL_TREE)
+    return NULL_TREE;
 
-      if (hsh->list)
-        {
-         /* We have two or more methods with the same name but
-            different types.  */
-         attr loop;
+  if (TREE_CODE (method) != TREE_VEC)
+    return method;
 
-         /* But just how different are those types?  If
-            -Wno-strict-selector-match is specified, we shall not
-            complain if the differences are solely among types with
-            identical size and alignment.  */
-         if (!warn_strict_selector_match)
-           {
-             for (loop = hsh->list; loop; loop = loop->next)
-               if (!comp_proto_with_proto (meth, loop->value, 0))
-                 goto issue_warning;
-
-             return meth;
-           }
-
-       issue_warning:
-         if (methods)
-           {
-             bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL;
-
-             warning_at (input_location, 0,
-                         "multiple methods named %<%c%E%> found",
-                         (is_class ? '+' : '-'),
-                         METHOD_SEL_NAME (meth));
-             inform (DECL_SOURCE_LOCATION (meth), "using %<%c%s%>",
-                     (type ? '-' : '+'),
-                     identifier_to_locale (gen_method_decl (meth)));
-           }
-         else
-           {
-             bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL;
-
-             warning_at (input_location, 0,
-                         "multiple selectors named %<%c%E%> found",
-                         (is_class ? '+' : '-'),
-                         METHOD_SEL_NAME (meth));
-             inform (DECL_SOURCE_LOCATION (meth), "found %<%c%s%>",
-                     (type ? '-' : '+'),
-                     identifier_to_locale (gen_method_decl (meth)));
-           }
-
-         for (loop = hsh->list; loop; loop = loop->next)
-           {
-             bool type = TREE_CODE (loop->value) == INSTANCE_METHOD_DECL;
-
-             inform (DECL_SOURCE_LOCATION (loop->value), "also found %<%c%s%>",
-                     (type ? '-' : '+'),
-                     identifier_to_locale (gen_method_decl (loop->value)));
-           }
-        }
+  /* We have two or more methods with the same name but different
+     types.  */
+  first_method = TREE_VEC_ELT (method, 0);
+  
+  /* But just how different are those types?  If
+     -Wno-strict-selector-match is specified, we shall not complain if
+     the differences are solely among types with identical size and
+     alignment.  */
+  if (!warn_strict_selector_match)
+    {
+      for (i = 0; i < TREE_VEC_LENGTH (method); i++)
+       if (!comp_proto_with_proto (first_method, TREE_VEC_ELT (method, i), 0))
+         goto issue_warning;
+      
+      return first_method;
     }
-  return meth;
+    
+ issue_warning:
+  if (methods)
+    {
+      bool type = TREE_CODE (first_method) == INSTANCE_METHOD_DECL;
+      
+      warning_at (input_location, 0,
+                 "multiple methods named %<%c%E%> found",
+                 (is_class ? '+' : '-'),
+                 METHOD_SEL_NAME (first_method));
+      inform (DECL_SOURCE_LOCATION (first_method), "using %<%c%s%>",
+             (type ? '-' : '+'),
+             identifier_to_locale (gen_method_decl (first_method)));
+    }
+  else
+    {
+      bool type = TREE_CODE (first_method) == INSTANCE_METHOD_DECL;
+      
+      warning_at (input_location, 0,
+                 "multiple selectors named %<%c%E%> found",
+                 (is_class ? '+' : '-'),
+                 METHOD_SEL_NAME (first_method));
+      inform (DECL_SOURCE_LOCATION (first_method), "found %<%c%s%>",
+             (type ? '-' : '+'),
+             identifier_to_locale (gen_method_decl (first_method)));
+    }
+  
+  for (i = 0; i < TREE_VEC_LENGTH (method); i++)
+    {
+      bool type = TREE_CODE (TREE_VEC_ELT (method, i)) == INSTANCE_METHOD_DECL;
+      
+      inform (DECL_SOURCE_LOCATION (TREE_VEC_ELT (method, i)), "also found %<%c%s%>",
+             (type ? '-' : '+'),
+             identifier_to_locale (gen_method_decl (TREE_VEC_ELT (method, i))));
+    }
+
+  return first_method;
 }
 
 /* If RECEIVER is a class reference, return the identifier node for
@@ -5294,17 +5290,18 @@ objc_build_message_expr (tree receiver, tree messa
 static tree
 lookup_method_in_hash_lists (tree sel_name, int is_class)
 {
-  hash method_prototype = NULL;
+  tree method_prototype = OBJC_MAP_NOT_FOUND;
 
   if (!is_class)
-    method_prototype = hash_lookup (nst_method_hash_list,
-                                   sel_name);
-
-  if (!method_prototype)
+    method_prototype = objc_map_get (instance_method_map, sel_name);
+  
+  if (method_prototype == OBJC_MAP_NOT_FOUND)
     {
-      method_prototype = hash_lookup (cls_method_hash_list,
-                                     sel_name);
+      method_prototype = objc_map_get (class_method_map, sel_name);
       is_class = 1;
+
+      if (method_prototype == OBJC_MAP_NOT_FOUND)
+       return NULL_TREE;
     }
 
   return check_duplicates (method_prototype, 1, is_class);
@@ -5714,21 +5711,19 @@ objc_build_selector_expr (location_t loc, tree sel
       /* Look the selector up in the list of all known class and
          instance methods (up to this line) to check that the selector
          exists.  */
-      hash hsh;
+      tree method;
 
       /* First try with instance methods.  */
-      hsh = hash_lookup (nst_method_hash_list, selname);
+      method = objc_map_get (instance_method_map, selname);
 
       /* If not found, try with class methods.  */
-      if (!hsh)
+      if (method == OBJC_MAP_NOT_FOUND)
        {
-         hsh = hash_lookup (cls_method_hash_list, selname);
-       }
+         method = objc_map_get (class_method_map, selname);
 
-      /* If still not found, print out a warning.  */
-      if (!hsh)
-       {
-         warning (0, "undeclared selector %qE", selname);
+         /* If still not found, print out a warning.  */
+         if (method == OBJC_MAP_NOT_FOUND)
+           warning (0, "undeclared selector %qE", selname);
        }
     }
 
@@ -5761,131 +5756,99 @@ build_ivar_reference (tree id)
   return (*runtime.build_ivar_reference) (input_location, base, id);
 }
 
-/* Compute a hash value for a given method SEL_NAME.  */
-
-static size_t
-hash_func (tree sel_name)
-{
-  const unsigned char *s
-    = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
-  size_t h = 0;
-
-  while (*s)
-    h = h * 67 + *s++ - 113;
-  return h;
-}
-
 static void
 hash_init (void)
 {
-  nst_method_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
-  cls_method_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+  instance_method_map = objc_map_alloc_ggc (1000);
+  class_method_map = objc_map_alloc_ggc (1000);
 
-  cls_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
-  als_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+  class_name_map = objc_map_alloc_ggc (200);
+  alias_name_map = objc_map_alloc_ggc (200);
 
-  ivar_offset_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
-
   /* Initialize the hash table used to hold the constant string objects.  */
   string_htab = htab_create_ggc (31, string_hash,
                                   string_eq, NULL);
 }
 
-/* This routine adds sel_name to the hash list. sel_name  is a class or alias
-   name for the class. If alias name, then value is its underlying class.
-   If class, the value is NULL_TREE. */
-
+/* Use the following to add a method to class_method_map or
+   instance_method_map.  It will add the method, keyed by the
+   METHOD_SEL_NAME.  If the method already exists, but with one or
+   more different prototypes, it will store a TREE_VEC in the map,
+   with the method prototypes in the vector.  */
 static void
-hash_class_name_enter (hash *hashlist, tree sel_name, tree value)
+insert_method_into_method_map (bool class_method, tree method)
 {
-  hash obj;
-  int slot = hash_func (sel_name) % SIZEHASHTABLE;
+  tree method_name = METHOD_SEL_NAME (method);
+  tree existing_entry;
+  objc_map_t map;
 
-  obj = ggc_alloc_hashed_entry ();
-  if (value != NULL_TREE)
-    {
-      /* Save the underlying class for the 'alias' in the hash table */
-      attr obj_attr = ggc_alloc_hashed_attribute ();
-      obj_attr->value = value;
-      obj->list = obj_attr;
-    }
+  if (class_method)
+    map = class_method_map;
   else
-    obj->list = 0;
-  obj->next = hashlist[slot];
-  obj->key = sel_name;
+    map = instance_method_map;
 
-  hashlist[slot] = obj;         /* append to front */
+  /* Check if the method already exists in the map.  */
+  existing_entry = objc_map_get (map, method_name);
 
-}
-
-/*
-   Searches in the hash table looking for a match for class or alias name.
-*/
-
-static hash
-hash_class_name_lookup (hash *hashlist, tree sel_name)
-{
-  hash target;
-
-  target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
-
-  while (target)
+  /* If not, we simply add it to the map.  */
+  if (existing_entry == OBJC_MAP_NOT_FOUND)
+    objc_map_put (map, method_name, method);
+  else
     {
-      if (sel_name == target->key)
-       return target;
+      tree new_entry;
+      
+      /* If an entry already exists, it's more complicated.  We'll
+        have to check whether the method prototype is the same or
+        not.  */
+      if (TREE_CODE (existing_entry) != TREE_VEC)
+       {
+         /* If the method prototypes are the same, there is nothing
+            to do.  */
+         if (comp_proto_with_proto (method, existing_entry, 1))
+           return;
 
-      target = target->next;
-    }
-  return 0;
-}
+         /* If not, create a vector to store both the method already
+            in the map, and the new one that we are adding.  */
+         new_entry = make_tree_vec (2);
+         
+         TREE_VEC_ELT (new_entry, 0) = existing_entry;
+         TREE_VEC_ELT (new_entry, 1) = method;
+       }
+      else
+       {
+         /* An entry already exists, and it's already a vector.  This
+            means that at least 2 different method prototypes were
+            already found, and we're considering registering yet
+            another one.  */
+         size_t i;
 
-/* WARNING!!!!  hash_enter is called with a method, and will peek
-   inside to find its selector!  But hash_lookup is given a selector
-   directly, and looks for the selector that's inside the found
-   entry's key (method) for comparison.  */
+         /* Check all the existing prototypes.  If any matches the
+            one we need to add, there is nothing to do because it's
+            already there.  */
+         for (i = 0; i < TREE_VEC_LENGTH (existing_entry); i++)
+           if (comp_proto_with_proto (method, TREE_VEC_ELT (existing_entry, i), 1))
+             return;
 
-static void
-hash_enter (hash *hashlist, tree method)
-{
-  hash obj;
-  int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
+         /* Else, create a new, bigger vector and add the new method
+            at the end of it.  This is inefficient but extremely
+            rare; in any sane program most methods have a single
+            prototype, and very few, if any, will have more than
+            2!  */
+         new_entry = make_tree_vec (TREE_VEC_LENGTH (existing_entry) + 1);
+         
+         /* Copy the methods from the existing vector.  */
+         for (i = 0; i < TREE_VEC_LENGTH (existing_entry); i++)
+           TREE_VEC_ELT (new_entry, i) = TREE_VEC_ELT (existing_entry, i);
+         
+         /* Add the new method at the end.  */
+         TREE_VEC_ELT (new_entry, i) = method;
+       }
 
-  obj = ggc_alloc_hashed_entry ();
-  obj->list = 0;
-  obj->next = hashlist[slot];
-  obj->key = method;
-
-  hashlist[slot] = obj;                /* append to front */
-}
-
-static hash
-hash_lookup (hash *hashlist, tree sel_name)
-{
-  hash target;
-
-  target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
-
-  while (target)
-    {
-      if (sel_name == METHOD_SEL_NAME (target->key))
-       return target;
-
-      target = target->next;
+      /* Store the new vector in the map.  */
+      objc_map_put (map, method_name, new_entry);
     }
-  return 0;
 }
 
-static void
-hash_add_attr (hash entry, tree value)
-{
-  attr obj;
-
-  obj = ggc_alloc_hashed_attribute ();
-  obj->next = entry->list;
-  obj->value = value;
-
-  entry->list = obj;           /* append to front */
-}
 ^L
 static tree
 lookup_method (tree mchain, tree method)
@@ -5988,31 +5951,6 @@ lookup_method_static (tree interface, tree ident,
     }
 }
 
-/* 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, 1);
-      for (loop = hsh->list; !already_there && loop; loop = loop->next)
-       already_there |= comp_proto_with_proto (method, loop->value, 1);
-      if (!already_there)
-       hash_add_attr (hsh, method);
-    }
-}
-
 static tree
 objc_add_method (tree klass, tree method, int is_class, bool is_optional)
 {
@@ -6135,10 +6073,10 @@ objc_add_method (tree klass, tree method, int is_c
     }
 
   if (is_class)
-    add_method_to_hash_list (cls_method_hash_list, method);
+    insert_method_into_method_map (true, method);
   else
     {
-      add_method_to_hash_list (nst_method_hash_list, method);
+      insert_method_into_method_map (false, method);
 
       /* Instance methods in root classes (and categories thereof)
         may act as class methods as a last resort.  We also add
@@ -6151,37 +6089,12 @@ objc_add_method (tree klass, tree method, int is_c
 
       if (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE
          || !CLASS_SUPER_NAME (klass))
-       add_method_to_hash_list (cls_method_hash_list, method);
+       insert_method_into_method_map (true, method);
     }
 
   return method;
 }
 
-static tree
-add_class (tree class_name, tree name)
-{
-  struct interface_tuple **slot;
-
-  /* Put interfaces on list in reverse order.  */
-  TREE_CHAIN (class_name) = interface_chain;
-  interface_chain = class_name;
-
-  if (interface_htab == NULL)
-    interface_htab = htab_create_ggc (31, hash_interface, eq_interface, NULL);
-  slot = (struct interface_tuple **)
-    htab_find_slot_with_hash (interface_htab, name,
-                             IDENTIFIER_HASH_VALUE (name),
-                             INSERT);
-  if (!*slot)
-    {
-      *slot = ggc_alloc_cleared_interface_tuple ();
-      (*slot)->id = name;
-    }
-  (*slot)->class_name = class_name;
-
-  return interface_chain;
-}
-
 static void
 add_category (tree klass, tree category)
 {
@@ -6951,8 +6864,8 @@ start_class (enum tree_code code, tree class_name,
         {
          warning (0, "cannot find interface declaration for %qE",
                   class_name);
-         add_class (implementation_template = objc_implementation_context,
-                    class_name);
+         add_interface (implementation_template = objc_implementation_context,
+                        class_name);
         }
 
       /* If a super class has been specified in the implementation,
@@ -6985,7 +6898,7 @@ start_class (enum tree_code code, tree class_name,
         warning (0, "duplicate interface declaration for class %qE", class_name);
 #endif
       else
-       add_class (klass, class_name);
+       add_interface (klass, class_name);
 
       if (protocol_list)
        CLASS_PROTOCOL_LIST (klass)
Index: gcc/objc/objc-act.h
===================================================================
--- gcc/objc/objc-act.h (revision 179864)
+++ gcc/objc/objc-act.h (working copy)
@@ -252,12 +252,6 @@ struct GTY(()) hashed_entry {
 
 #define SIZEHASHTABLE          257
 
-extern GTY ((length ("SIZEHASHTABLE"))) hash *nst_method_hash_list;
-extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_method_hash_list;
-
-extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_name_hash_list;
-extern GTY ((length ("SIZEHASHTABLE"))) hash *als_name_hash_list;
-
 /* An array of all the local variables in the current function that
    need to be marked as volatile.  */
 extern GTY(()) VEC(tree,gc) *local_variables_to_volatilize;
Index: gcc/objc/objc-map.c
===================================================================
--- gcc/objc/objc-map.c (revision 0)
+++ gcc/objc/objc-map.c (revision 0)
@@ -0,0 +1,161 @@
+/* objc-map.c -- Implementation of map data structures for ObjC compiler
+   Copyright 2011 Free Software Foundation, Inc.
+   Written by Nicola Pero <nicola.pero@meta-innovation.com>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program; if not, write to the Free Software
+Foundation, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "ggc.h"
+#include "objc-map.h"
+
+#define OUT_OF_MEMORY { fprintf (stderr, "Out of memory\n"); abort (); }
+
+static
+size_t
+ATTRIBUTE_PURE
+next_power_of_two (size_t x)
+{
+  size_t result = 1;
+
+  if (x < 2)
+    return 2;
+
+  /* Avoid the long calculation if x is already a power of two.  Since
+     we internally always increase/shrink tables by powers of 2, the
+     calculation should only be done once, when the table is first
+     set up.  */
+  if ((x & (x - 1)) == 0)
+    return x;
+
+  /* Calculate log_2 by counting how many times we can divide by 2
+     before reaching 0.  */
+  while (x > 0)
+    {
+      x = x >> 1;
+      result = result << 1;
+    }
+  return result;
+}
+
+objc_map_t
+objc_map_alloc_ggc (size_t initial_capacity)
+{
+  objc_map_t map = (objc_map_t) ggc_internal_cleared_vec_alloc_stat (1, sizeof (struct objc_map_private));
+  if (map == NULL)
+    OUT_OF_MEMORY;
+  
+  initial_capacity = next_power_of_two (initial_capacity);
+  
+  map->number_of_slots = initial_capacity;
+  map->mask = initial_capacity - 1;
+  map->maximum_load_factor = 70;
+  map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100;
+
+  map->slots = (tree *)ggc_internal_cleared_vec_alloc_stat (initial_capacity, sizeof (tree));
+  map->values = (tree *)ggc_internal_cleared_vec_alloc_stat (initial_capacity, sizeof (tree));
+
+  if (map->slots == NULL)
+    OUT_OF_MEMORY;
+  
+  if (map->values == NULL)
+    OUT_OF_MEMORY;
+
+  return map;
+}
+
+void
+objc_map_set_maximum_load_factor (objc_map_t map, int number_between_zero_and_one_hundred)
+{
+  if (map->number_of_non_empty_slots != 0)
+    return;
+
+  map->maximum_load_factor = number_between_zero_and_one_hundred;
+  map->max_number_of_non_empty_slots = (map->number_of_slots * number_between_zero_and_one_hundred) / 100;
+}
+
+int
+objc_map_maximum_load_factor (objc_map_t map)
+{
+  return map->maximum_load_factor;
+}
+
+static void
+objc_map_private_resize (objc_map_t map, size_t new_number_of_slots)
+{
+  tree *old_slots = map->slots;
+  tree *old_values = map->values;
+  size_t i, old_number_of_slots = map->number_of_slots;
+  
+  if (new_number_of_slots < (map->number_of_non_empty_slots))
+    new_number_of_slots = 2 * map->number_of_non_empty_slots;
+
+  new_number_of_slots = next_power_of_two (new_number_of_slots);
+  
+  map->number_of_slots = new_number_of_slots;
+  map->mask = map->number_of_slots - 1;
+  map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100;
+
+
+  map->slots = (tree *)ggc_internal_cleared_vec_alloc_stat (map->number_of_slots, sizeof (tree));
+  map->values = (tree *)ggc_internal_cleared_vec_alloc_stat (map->number_of_slots, sizeof (tree));
+
+  if (map->slots == NULL)
+    OUT_OF_MEMORY;
+
+  if (map->values == NULL)
+    OUT_OF_MEMORY;
+
+  for (i = 0; i < old_number_of_slots; i++)
+    if (old_slots[i] != OBJC_MAP_PRIVATE_EMPTY_SLOT)
+      {
+       size_t k = IDENTIFIER_HASH_VALUE (old_slots[i]) & map->mask;
+       
+       if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+         {
+           map->slots[k] = old_slots[i];
+           map->values[k] = old_values[i];
+         }
+       else
+         {
+           size_t j = 1;
+           while (1)
+             {
+               k = (k + j) & map->mask;
+               if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+                 {
+                   map->slots[k] = old_slots[i];
+                   map->values[k] = old_values[i];
+                   break;
+                 }
+               j++;
+             }
+         }
+      }
+
+  ggc_free (old_slots);
+  ggc_free (old_values);
+}
+
+void
+objc_map_private_grow (struct objc_map_private *map)
+{
+  objc_map_private_resize (map, map->number_of_slots * 2);
+}
+
+#include "gt-objc-objc-map.h"
Index: gcc/objc/objc-map.h
===================================================================
--- gcc/objc/objc-map.h (revision 0)
+++ gcc/objc/objc-map.h (revision 0)
@@ -0,0 +1,309 @@
+/* objc-map.h -- Implementation of map data structures for ObjC compiler
+   Copyright 2011 Free Software Foundation, Inc.
+   Written by Nicola Pero <nicola.pero@meta-innovation.com>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program; if not, write to the Free Software
+Foundation, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#ifndef OBJC_MAP_H
+#define OBJC_MAP_H
+
+/* A map is a data structure that maps a key to a value.  In this file
+   we currently have maps that can map a GCC identifier (a tree) to
+   some other GCC tree.  This is what the ObjC frontend mostly needs:
+   being able to look up an identifier into an ObjC data structure.  A
+   typical usage is mapping ObjC class names (as identifiers) to a
+   tree representing the class.
+
+   This implementation is fast.  :-) */
+
+/**
+ ** Private definitions.
+ **/
+
+/* We include private declaration and definitions that are required to
+   provide the implementation of inline functions.  You should ignore
+   these definitions (and the implementation of the inline functions)
+   as they are not part of the public API and may change.  */
+typedef unsigned int objc_map_private_hash_t;
+
+/* This is used as sentinel.  */
+#define OBJC_MAP_PRIVATE_EMPTY_SLOT (tree)0
+
+struct GTY(()) objc_map_private {
+  /* Total number of slots.  This is the maximum number of elements
+     that can be currently stored in the map before resizing.  This is
+     the number of slots in the C array.  Important: this is
+     guaranteed to be a power of 2.  When we create (or resize) the
+     map, we round up the size to the next power of 2.  This allows us
+     to convert a hash to a position in the hashtable by simply doing
+     "position = hash & mask", where mask is number_of_slots - 1
+     instead of using a modulo (which requires a division).  */
+  size_t number_of_slots;
+
+  /* This is number_of_slots - 1, precomputed.  */
+  size_t mask;
+
+  /* Number of slots that are not empty (ie, that are active).  We
+     keep counts using this variable which can easily be checked
+     against max_number_of_non_empty_slots.  */
+  size_t number_of_non_empty_slots;
+
+  /* This is the load factor limit.  When the number of non empty
+     slots equals this number, we need to resize the array.  This is
+     calculated once, when the slots are resized, and then kept cached
+     so it can be compared quickly when elements are added.  */
+  size_t max_number_of_non_empty_slots;
+
+  /* The maximum load factor.  */
+  int maximum_load_factor;
+
+  /* These are the keys.  */
+  tree * GTY ((length ("%h.number_of_slots"))) slots;
+
+  /* These are the values.  values[i] is the the value corresponding
+     to slots[i].  */
+  tree * GTY ((length ("%h.number_of_slots"))) values;
+};
+
+/* Private functions used to resize the map.  They may be called by
+   the inline functions when adding elements.  */
+extern void
+objc_map_private_grow (struct objc_map_private *map);
+
+
+/**
+ ** The definition of a map.
+ **/
+typedef struct objc_map_private *objc_map_t;
+
+
+/**
+ ** Creating a map.
+ **/
+
+/* objc_map_alloc_ggc() creates a new map which is under GGC.  The initial
+   capacity must be specified as an argument; this is used to size the map
+   when it is created.  */
+objc_map_t objc_map_alloc_ggc (size_t initial_capacity);
+
+/**
+ ** Performance tuning.
+ **/
+
+/* Set a maximum load factor for the data structure.  This is the main
+   tuning parameter to improve performance (at the expense of
+   memory).  */
+void objc_map_set_maximum_load_factor (objc_map_t map, int number_between_zero_and_one_hundred);
+
+/* Read the maximum load factor.  */
+int objc_map_maximum_load_factor (objc_map_t map);
+
+
+/**
+ ** Getting the value corresponding to a key.
+ **/
+
+/* This is the value returned by objc_map_get() when the value
+   corresponding to a key is not found.  */
+#define OBJC_MAP_NOT_FOUND (tree)1
+
+/* objc_map_get() returns the value associated with a certain key,
+   or OBJC_MAP_NOT_FOUND if there is no value associated with that key.
+   Note that you can also use it to simply check if the map contains a
+   pair with a certain key; just compare the result of calling
+   objc_map_get() to OBJC_MAP_NOT_FOUND.
+
+   It is essential to always check the results of the call to make
+   sure it is not OBJC_MAP_NOT_FOUND.
+
+   NULL is a valid value, so a key can be inserted into a map with
+   value NULL, and objc_map_get() will return NULL in that case.
+   So a result of NULL means that they key *was* found, and the value
+   associated with it was NULL.  */
+static inline tree
+objc_map_get (objc_map_t map, /* struct tree_identifier * */tree key)
+{
+  /* The inline implementation is private and may change without notice.  */
+  objc_map_private_hash_t hash = IDENTIFIER_HASH_VALUE (key);
+  size_t i = hash & map->mask;
+  size_t j = 1;
+
+  if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+    return OBJC_MAP_NOT_FOUND;
+
+  if (map->slots[i] == key)
+    return map->values[i];
+  
+  while (1)
+    {
+      i = (i + j) & map->mask;
+      
+      if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+       return OBJC_MAP_NOT_FOUND;
+      
+      if (map->slots[i] == key)
+       return map->values[i];
+
+      j++;
+    }
+}
+
+/* objc_map_put() puts a key/value pair into the map.  If the map does
+   not contain the key, it is added to it with the specified value.
+   If the map already contains the key, the previous value is replaced
+   with the new one.
+
+   You can use any identifier as key, with the exception of NULL.
+
+   You can use any tree as value, including NULL.  */
+static inline
+void objc_map_put (objc_map_t map, /*struct tree_identifier * */tree key, tree value)
+{
+  /* The inline implementation is private and may change without notice.  */
+  objc_map_private_hash_t hash = IDENTIFIER_HASH_VALUE (key);
+  size_t i, j = 0;
+
+  if (map->number_of_non_empty_slots == map->max_number_of_non_empty_slots)
+    objc_map_private_grow (map);
+
+  i = hash & map->mask;
+    
+  while (1)
+    {
+      if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+       {
+         map->number_of_non_empty_slots++;
+         map->slots[i] = key;
+         map->values[i] = value;
+         return;
+       }
+      if (map->slots[i] == key)
+       {
+         map->values[i] = value;
+         return;
+       }
+
+      j++;
+      i = (i + j) & map->mask;
+    }
+}
+
+/**
+ ** Iterating over a map using an iterator.
+ **/
+
+/* When using iterators you can iterate directly on the elements in
+   the map, and take an action over each one.
+
+   Here is how you iterate over a hmap_pointer using iterators:
+
+   objc_map_iterator_t i;
+
+   objc_map_iterator_initialize (map, &i);
+
+   while (objc_map_iterator_move_to_next (map, &i))
+     {
+       tree p = objc_map_iterator_current_key (map, i);
+       tree q = objc_map_iterator_current_value (map, i);
+
+       ... do something with p and q ...
+     }
+
+   You'll notice that the functions that modify the iterator (to
+   initialize it, or move it to the next element) take a pointer to it
+   as argument (as in "&i"), while the functions that only read its
+   state (to read the current key/value, or remove the current
+   key/value from the map) take it as a direct argument (as in "i").
+
+   Note that all the objc_map_iterator_*() functions are inline and if
+   you follow the pattern above, the compiler should be able to inline
+   everything into a very efficient loop, roughly equivalent to
+   hand-writing a C loop that iterates directly onto the hmap_pointer
+   internal data structures.  */
+
+/* A objc_map_iterator_t variable encapsulates the state of an
+   iteration.  The fact that this is actually a size_t (pointing to
+   the index of the slot that we return next) is an internal, private
+   detail of the implementation and may change without notice.  */
+typedef size_t objc_map_iterator_t;
+
+/* Initialize an iterator to iterate over the specified objc_map.  You
+   must use this before starting the iteration, to get a working
+   iterator.  */
+static inline
+void
+objc_map_iterator_initialize (objc_map_t map ATTRIBUTE_UNUSED, objc_map_iterator_t *i)
+{
+  /* The inline implementation is private and may change without notice.  */
+  /* This is trivial, but the same API would work to initialize more
+     complicated iterators.  */
+  *i = 0;
+}
+
+#define OBJC_MAP_FAILURE 0
+#define OBJC_MAP_SUCCESS 1
+
+/* Move the iterator to the next key/value pair, and return
+   OBJC_MAP_SUCCESS if there is such a key/value pair, and
+   OBJC_MAP_FAILURE if there are no more ones.  The iterator must have
+   been initialized using objc_map_iterator_initialize().  Note that
+   because this function is modifying the iterator, you need to pass a
+   pointer to it.  */
+static inline
+int
+objc_map_iterator_move_to_next (objc_map_t map, objc_map_iterator_t *i)
+{
+  /* The inline implementation is private and may change without notice.  */
+  while (1)
+    {
+      void *slot;
+      if (*i == map->number_of_slots)
+       return OBJC_MAP_FAILURE;
+      
+      slot = map->slots[*i];
+      *i = *i + 1;
+      if (slot != OBJC_MAP_PRIVATE_EMPTY_SLOT)
+       return OBJC_MAP_SUCCESS;
+    }
+}
+
+/* Return the current key.  You can only call it after you have called
+   objc_map_iterator_move_to_next() at least once (to move to the
+   first element), and only if the last call returned
+   OBJC_MAP_SUCCESS.  The behaviour is otherwise undefined, probably a
+   segmentation fault.  */
+static inline
+tree
+objc_map_iterator_current_key (objc_map_t map, objc_map_iterator_t i)
+{
+  /* The inline implementation is private and may change without notice.  */
+  return map->slots[i - 1];
+}
+
+/* Return the current value.  You can only call it after you have
+   called objc_map_iterator_move_to_next() at least once (to move to
+   the first element), and only if the last call returned
+   OBJC_MAP_SUCCESS.  The behaviour is otherwise undefined, probably a
+   segmentation fault.  */
+static inline
+tree
+objc_map_iterator_current_value (objc_map_t map, objc_map_iterator_t i)
+{
+  /* The inline implementation is private and may change without notice.  */
+  return map->values[i - 1];
+}
+
+#endif /* OBJC_MAP_H */
Index: gcc/objcp/Make-lang.in
===================================================================
--- gcc/objcp/Make-lang.in      (revision 179864)
+++ gcc/objcp/Make-lang.in      (working copy)
@@ -58,6 +58,7 @@ OBJCXX_OBJS = objcp/objcp-act.o objcp/objcp-lang.o
    objcp/objc-next-runtime-abi-01.o \
    objcp/objc-next-runtime-abi-02.o \
    objcp/objc-encoding.o \
+   objcp/objc-map.o \
    $(CXX_AND_OBJCXX_OBJS)
 
 obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o
@@ -149,6 +150,7 @@ objcp/objcp-act.o : objc/objc-act.c \
    $(RTL_H) $(EXPR_H) $(TARGET_H) \
    objcp/objcp-decl.h \
    objc/objc-encoding.h \
+   objc/objc-map.h \
    objc/objc-runtime-hooks.h \
    objc/objc-runtime-shared-support.h \
    objcp/objcp-decl.h
@@ -165,6 +167,14 @@ objcp/objc-encoding.o : objc/objc-encoding.c \
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
                $(OUTPUT_OPTION)
 
+objcp/objc-map.o : objc/objc-map.c \
+   $(START_HDRS) \
+   $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+   $(OBSTACK_H) \
+   objc/objc-map.h
+       $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
+               $(OUTPUT_OPTION)
+
 po-generated:
 
 #^L
Index: gcc/objcp/ChangeLog
===================================================================
--- gcc/objcp/ChangeLog (revision 179864)
+++ gcc/objcp/ChangeLog (working copy)
@@ -1,3 +1,10 @@
+2011-10-14  Nicola Pero  <nicola.pero@meta-innovation.com>
+
+       * Make-lang.in (OBJCXX_OBJS): Added objc-map.o.
+       (objcp/objc-map.o): New rule.
+       (objcp/objcp-act.o): Depend on objc/objc-map.h.
+       * config-lang.in (gtfiles): Added objc-map.h.
+
 2011-07-11  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * Make-lang.in (objcp/objc-runtime-shared-support.o): Do not
Index: gcc/objcp/config-lang.in
===================================================================
--- gcc/objcp/config-lang.in    (revision 179864)
+++ gcc/objcp/config-lang.in    (working copy)
@@ -46,5 +46,5 @@ subdir_requires="objc cp"
 # This list is separated in two parts: the first one is identical to
 # the C++ one, the second one contains our ObjC++ additions.
 gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \
-\$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c"
+\$(srcdir)/objc/objc-map.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c"

