[C++ PATCH] hash-table for extern-c fns.
authorNathan Sidwell <nathan@acm.org>
Fri, 6 Oct 2017 14:19:23 +0000 (14:19 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Fri, 6 Oct 2017 14:19:23 +0000 (14:19 +0000)
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

gcc/cp/ChangeLog
gcc/cp/name-lookup.c

index ef053a51cd4dc0276ec0f1ce90f5eda7dc7daa4f..7292fee2d6750117f0a142efcadb5a00d493d3ac 100644 (file)
@@ -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.
index 84f7381cc6f74cb444b97defa086e7305cca82a6..fb86310c88458a92e5e6f35e4c115cb4bce5f523 100644 (file)
@@ -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;
 }