aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2017-10-06 14:19:23 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2017-10-06 14:19:23 +0000
commit9bc3f4206615c69934344ea3681f9446bdc1a1f5 (patch)
tree1f36d628d50134cf505369a6074ff953c04e9e15
parent513d5564225f8baa2ddeafde9edb9e10b62e30ce (diff)
downloadgcc-9bc3f4206615c69934344ea3681f9446bdc1a1f5.zip
gcc-9bc3f4206615c69934344ea3681f9446bdc1a1f5.tar.gz
gcc-9bc3f4206615c69934344ea3681f9446bdc1a1f5.tar.bz2
[C++ PATCH] hash-table for extern-c fns.
https://gcc.gnu.org/ml/gcc-patches/2017-10/msg00376.html Use hash_table for extern "C" names * name-lookup.c (extern_c_fns): Use hash_table. (check_extern_c_conflict): Adjust. (c_linkage_bindings): Adjust. From-SVN: r253493
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/name-lookup.c50
2 files changed, 40 insertions, 15 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ef053a5..7292fee 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
2017-10-06 Nathan Sidwell <nathan@acm.org>
+ Use hash_table for extern "C" names
+ * name-lookup.c (extern_c_fns): Use hash_table.
+ (check_extern_c_conflict): Adjust.
+ (c_linkage_bindings): Adjust.
+
Use hash_table for namespace bindings
* cp-tree.h (struct named_decl_hash): New.
(lang_decl_ns): Change type of bindings field.
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 84f7381..fb86310 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -2511,9 +2511,9 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
return decl;
}
-/* Map of identifiers to extern C functions (or LISTS thereof). */
+/* Table of identifiers to extern C functions (or LISTS thereof). */
-static GTY(()) hash_map<lang_identifier *, tree> *extern_c_fns;
+static GTY(()) hash_table<named_decl_hash> *extern_c_fns;
/* DECL has C linkage. If we have an existing instance, make sure it
has the same exception specification [7.5, 7.6]. If there's no
@@ -2527,17 +2527,15 @@ check_extern_c_conflict (tree decl)
return;
if (!extern_c_fns)
- extern_c_fns = hash_map<lang_identifier *,tree>::create_ggc (127);
+ extern_c_fns = hash_table<named_decl_hash>::create_ggc (127);
- bool existed;
- tree *slot = &extern_c_fns->get_or_insert (DECL_NAME (decl), &existed);
- if (!existed)
- *slot = decl;
- else
+ tree *slot = extern_c_fns
+ ->find_slot_with_hash (DECL_NAME (decl),
+ IDENTIFIER_HASH_VALUE (DECL_NAME (decl)), INSERT);
+ if (tree old = *slot)
{
- tree old = *slot;
- if (TREE_CODE (old) == TREE_LIST)
- old = TREE_VALUE (old);
+ if (TREE_CODE (old) == OVERLOAD)
+ old = OVL_FUNCTION (old);
int mismatch = 0;
if (DECL_CONTEXT (old) == DECL_CONTEXT (decl))
@@ -2563,9 +2561,24 @@ check_extern_c_conflict (tree decl)
"due to different exception specifications");
}
else
- /* Chain it on for c_linkage_binding's use. */
- *slot = tree_cons (NULL_TREE, decl, *slot);
+ {
+ if (old == *slot)
+ /* The hash table expects OVERLOADS, so construct one with
+ OLD as both the function and the chain. This allocate
+ an excess OVERLOAD node, but it's rare to have multiple
+ extern "C" decls of the same name. And we save
+ complicating the hash table logic (which is used
+ elsewhere). */
+ *slot = ovl_make (old, old);
+
+ slot = &OVL_CHAIN (*slot);
+
+ /* Chain it on for c_linkage_binding's use. */
+ *slot = tree_cons (NULL_TREE, decl, *slot);
+ }
}
+ else
+ *slot = decl;
}
/* Returns a list of C-linkage decls with the name NAME. Used in
@@ -2575,8 +2588,15 @@ tree
c_linkage_bindings (tree name)
{
if (extern_c_fns)
- if (tree *slot = extern_c_fns->get (name))
- return *slot;
+ if (tree *slot = extern_c_fns
+ ->find_slot_with_hash (name, IDENTIFIER_HASH_VALUE (name), NO_INSERT))
+ {
+ tree result = *slot;
+ if (TREE_CODE (result) == OVERLOAD)
+ result = OVL_CHAIN (result);
+ return result;
+ }
+
return NULL_TREE;
}