summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/gengtype.c5
-rw-r--r--gcc/objc/ChangeLog51
-rw-r--r--gcc/objc/Make-lang.in10
-rw-r--r--gcc/objc/config-lang.in2
-rw-r--r--gcc/objc/objc-act.c507
-rw-r--r--gcc/objc/objc-act.h6
-rw-r--r--gcc/objc/objc-map.c161
-rw-r--r--gcc/objc/objc-map.h309
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c1
-rw-r--r--gcc/objcp/ChangeLog7
-rw-r--r--gcc/objcp/Make-lang.in10
-rw-r--r--gcc/objcp/config-lang.in2
13 files changed, 770 insertions, 306 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c6f47f9ffc5..5c82e9b837d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2011-10-14 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * gengtype.c (files_rules): Added rules for objc/objc-map.h and
+ objc/objc-map.c.
+
2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/17212
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 0820741a051..6063d81daa5 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1817,6 +1817,11 @@ struct file_rule_st files_rules[] = {
REG_EXTENDED, NULL_REGEX,
"gt-objc-objc-act.h", "objc/objc-act.c", NULL_FRULACT },
+ /* objc/objc-map.h gives gt-objc-objc-map.h for objc/objc-map.c ! */
+ { DIR_PREFIX_REGEX "objc/objc-map\\.h$",
+ REG_EXTENDED, NULL_REGEX,
+ "gt-objc-objc-map.h", "objc/objc-map.c", NULL_FRULACT },
+
/* General cases. For header *.h and source *.c files, we need
* special actions to handle the language. */
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index e195ed5dd1b..e5fa097c485 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -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
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index f9b3907fe1c..5cca11a6b4d 100644
--- a/gcc/objc/Make-lang.in
+++ b/gcc/objc/Make-lang.in
@@ -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:
#
diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in
index 0de0650c0de..48f8582d74c 100644
--- a/gcc/objc/config-lang.in
+++ b/gcc/objc/config-lang.in
@@ -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"
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 72a486d9c83..396d748849f 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -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) ATTRIBUTE_NORETURN;
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_ident)
#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,16 +3421,17 @@ 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_code modifycode, tree rhs)
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, tree method,
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;
-
- if (hsh)
- {
- meth = hsh->key;
-
- if (hsh->list)
- {
- /* We have two or more methods with the same name but
- different types. */
- attr loop;
-
- /* 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;
+ tree first_method;
+ size_t i;
- 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;
+ if (method == NULL_TREE)
+ return NULL_TREE;
- inform (DECL_SOURCE_LOCATION (loop->value), "also found %<%c%s%>",
- (type ? '-' : '+'),
- identifier_to_locale (gen_method_decl (loop->value)));
- }
- }
+ if (TREE_CODE (method) != TREE_VEC)
+ return method;
+
+ /* 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;
+ }
+
+ 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)));
}
- return meth;
+ 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 message_args)
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 selnamelist)
/* 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);
-
- cls_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
- als_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+ instance_method_map = objc_map_alloc_ggc (1000);
+ class_method_map = objc_map_alloc_ggc (1000);
- ivar_offset_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+ class_name_map = objc_map_alloc_ggc (200);
+ alias_name_map = objc_map_alloc_ggc (200);
/* 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;
-
- hashlist[slot] = obj; /* append to front */
+ map = instance_method_map;
-}
+ /* 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;
-
- target = target->next;
- }
- return 0;
-}
-
-/* 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. */
-
-static void
-hash_enter (hash *hashlist, tree method)
-{
- hash obj;
- int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
-
- 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;
+ 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 = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
+ /* 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;
+
+ /* 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;
- while (target)
- {
- if (sel_name == METHOD_SEL_NAME (target->key))
- return target;
+ /* 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;
+ }
- 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 */
-}
static tree
lookup_method (tree mchain, tree method)
@@ -5988,31 +5951,6 @@ lookup_method_static (tree interface, tree ident, int flags)
}
}
-/* 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_class, bool is_optional)
}
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_class, bool is_optional)
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, tree super_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, tree super_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)
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 33f90fdb785..e958e669af0 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -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;
diff --git a/gcc/objc/objc-map.c b/gcc/objc/objc-map.c
new file mode 100644
index 00000000000..77a98c1d825
--- /dev/null
+++ b/gcc/objc/objc-map.c
@@ -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"
diff --git a/gcc/objc/objc-map.h b/gcc/objc/objc-map.h
new file mode 100644
index 00000000000..c4565de186e
--- /dev/null
+++ b/gcc/objc/objc-map.h
@@ -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 */
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index 56df2afaf0c..4512c846cc0 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -231,6 +231,7 @@ static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
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
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 51ab2a5016a..bed3b9dcd25 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -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
diff --git a/gcc/objcp/Make-lang.in b/gcc/objcp/Make-lang.in
index 3dac1735e15..4255bd63909 100644
--- a/gcc/objcp/Make-lang.in
+++ b/gcc/objcp/Make-lang.in
@@ -58,6 +58,7 @@ OBJCXX_OBJS = objcp/objcp-act.o objcp/objcp-lang.o objcp/objcp-decl.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:
#
diff --git a/gcc/objcp/config-lang.in b/gcc/objcp/config-lang.in
index e80666da5b5..5fd0f06b33b 100644
--- a/gcc/objcp/config-lang.in
+++ b/gcc/objcp/config-lang.in
@@ -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"