[C++] don't put conv-op names in identifier hash

Message ID 5221953b-ac3e-1574-a25d-10a5da3cb5e1@acm.org
State New
Headers show
Series
  • [C++] don't put conv-op names in identifier hash
Related show

Commit Message

Nathan Sidwell Sept. 13, 2017, 12:49 p.m.
This patch changes the conv-op identifier node creation.  Conv-ops are 
never looked up by name, and there's no need for them to be in the 
identifier table.  Which also means there's no need for them to have 
distinct names.

This patch implements that.  conv-op names are directly cloned from the 
regular 'conv_op_identifier'. They are only findable via make_conv_op_name.

Jason, you asked about whether we could dispense with stashing conv-op 
target types in the identifier_node.  That looked more complicated, we'd 
need to (at least) address
1) pretty printing.  That passes DECL_NAME, expecting to print 'operator 
TYPE' from it.
2) parsing.  That passes the identifier as part of declarator_name into 
grokdeclarator and friends.
3) class-scope name lookup.  That expects an identifier and from that 
find the right conversion function

I'm sure all that can be fixed with additional args or whatever, but I'm 
not going there now.

nathan

Patch

2017-09-13  Nathan Sidwell  <nathan@acm.org>

	Conv-op identifers not in identifier hash table
	* lex.c (conv_type_hasher): Make member fns inline.
	(make_conv_op_name): Directly clone conv_op_identifier.

Index: lex.c
===================================================================
--- lex.c	(revision 252076)
+++ lex.c	(working copy)
@@ -531,10 +531,24 @@  unqualified_fn_lookup_error (cp_expr nam
   return unqualified_name_lookup_error (name, loc);
 }
 
+
+/* Hasher for the conversion operator name hash table.  */
 struct conv_type_hasher : ggc_ptr_hash<tree_node>
 {
-  static hashval_t hash (tree);
-  static bool equal (tree, tree);
+  /* Hash NODE, an identifier node in the table.  TYPE_UID is
+     suitable, as we're not concerned about matching canonicalness
+     here.  */
+  static hashval_t hash (tree node)
+  {
+    return (hashval_t) TYPE_UID (TREE_TYPE (node));
+  }
+
+  /* Compare NODE, an identifier node in the table, against TYPE, an
+     incoming TYPE being looked up.  */
+  static bool equal (tree node, tree type)
+  {
+    return TREE_TYPE (node) == type;
+  }
 };
 
 /* This hash table maps TYPEs to the IDENTIFIER for a conversion
@@ -543,57 +557,41 @@  struct conv_type_hasher : ggc_ptr_hash<t
 
 static GTY (()) hash_table<conv_type_hasher> *conv_type_names;
 
-/* Hash a node (VAL1) in the table.  */
-
-hashval_t
-conv_type_hasher::hash (tree val)
-{
-  return (hashval_t) TYPE_UID (TREE_TYPE (val));
-}
-
-/* Compare VAL1 (a node in the table) with VAL2 (a TYPE).  */
-
-bool
-conv_type_hasher::equal (tree val1, tree val2)
-{
-  return TREE_TYPE (val1) == val2;
-}
-
-/* Return an identifier for a conversion operator to TYPE.  We can
-   get from the returned identifier to the type.  */
+/* Return an identifier for a conversion operator to TYPE.  We can get
+   from the returned identifier to the type.  We store TYPE, which is
+   not necessarily the canonical type,  which allows us to report the
+   form the user used in error messages.  All these identifiers are
+   not in the identifier hash table, and have the same string name.
+   These IDENTIFIERS are not in the identifier hash table, and all
+   have the same IDENTIFIER_STRING.  */
 
 tree
 make_conv_op_name (tree type)
 {
-  tree *slot;
-  tree identifier;
-
   if (type == error_mark_node)
     return error_mark_node;
 
   if (conv_type_names == NULL)
     conv_type_names = hash_table<conv_type_hasher>::create_ggc (31);
 
-  slot = conv_type_names->find_slot_with_hash (type,
-					       (hashval_t) TYPE_UID (type),
-					       INSERT);
-  identifier = *slot;
+  tree *slot = conv_type_names->find_slot_with_hash
+    (type, (hashval_t) TYPE_UID (type), INSERT);
+  tree identifier = *slot;
   if (!identifier)
     {
-      char buffer[64];
-
-       /* Create a unique name corresponding to TYPE.  */
-      sprintf (buffer, "operator %lu",
-	       (unsigned long) conv_type_names->elements ());
-      identifier = get_identifier (buffer);
-      *slot = identifier;
+      /* Create a raw IDENTIFIER outside of the identifier hash
+	 table.  */
+      identifier = copy_node (conv_op_identifier);
+
+      /* Just in case something managed to bind.  */
+      IDENTIFIER_BINDING (identifier) = NULL;
+      IDENTIFIER_LABEL_VALUE (identifier) = NULL_TREE;
 
       /* Hang TYPE off the identifier so it can be found easily later
 	 when performing conversions.  */
       TREE_TYPE (identifier) = type;
 
-      /* Set the identifier kind so we know later it's a conversion.  */
-      set_identifier_kind (identifier, cik_conv_op);
+      *slot = identifier;
     }
 
   return identifier;