diff mbox

[C++] Hidden name removal

Message ID 54c5f328-e351-cefe-e788-768f7bdccbea@acm.org
State New
Headers show

Commit Message

Nathan Sidwell May 24, 2017, 3:59 p.m. UTC
Now that overloads are kept ordered, I can replace the existing 
remove_hidden_names fn with ovl_skip_hidden.

The former works by scanning the overloads, then if it discovers a 
hidden one, copying the list (from the beginning) omitting the hidden 
ones.  Now, overloads aren't usually huge, but this forces scanning on 
every lookup, and is O(N^2), so bad.  ovl_skip_hidden simply drops the 
OVL_HIDDEN_P nodes at the start of an overload.  Often doing nothing.

For extra badness, lookup_name_real was applying remove_hidden_names to 
a result that had already had it run!

Applied to trunk.

nathan
diff mbox

Patch

2017-05-24  Nathan Sidwell  <nathan@acm.org>

	* cp-tree.h (ovl_skip_hidden): Declare.
	* tree.c (ovl_skip_hidden): New.
	* name-lookup.c (arg_assoc_namespace): Call ovl_skip_hidden.
	(lookup_arg_dependent_1): Likewise.
	(ambiguous_decl): Use DECL_HIDDEN_P, ovl_skip_hidden.
	(hidden_name_p, remove_hidden_names): Delete.
	(lookup_name_real_1): Do not strip hidden names.
	* name-lookup.h (hidden_name_p, remove_hidden_names): Delete.

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 248422)
+++ cp/cp-tree.h	(working copy)
@@ -6852,6 +6852,7 @@  extern tree ovl_make				(tree fn,
 						 tree next = NULL_TREE);
 extern tree ovl_insert				(tree fn, tree maybe_ovl,
 						 bool using_p = false);
+extern tree ovl_skip_hidden			(tree);
 extern tree lookup_add				(tree fns, tree lookup);
 extern void lookup_keep				(tree lookup, bool keep);
 extern int is_overloaded_fn			(tree);
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 248422)
+++ cp/name-lookup.c	(working copy)
@@ -275,14 +275,10 @@  arg_assoc_namespace (struct arg_lookup *
   if (!value)
     return false;
 
+  value = ovl_skip_hidden (value);
+  
   for (; value; value = OVL_NEXT (value))
     {
-      /* We don't want to find arbitrary hidden functions via argument
-	 dependent lookup.  We only want to find friends of associated
-	 classes, which we'll do via arg_assoc_class.  */
-      if (hidden_name_p (OVL_CURRENT (value)))
-	continue;
-
       if (add_function (k, OVL_CURRENT (value)))
 	return true;
     }
@@ -630,7 +626,7 @@  lookup_arg_dependent_1 (tree name, tree
   /* Remove any hidden friend functions from the list of functions
      found so far.  They will be added back by arg_assoc_class as
      appropriate.  */
-  fns = remove_hidden_names (fns);
+  fns = ovl_skip_hidden (fns);
 
   k.name = name;
   k.args = args;
@@ -4347,7 +4343,7 @@  ambiguous_decl (struct scope_binding *ol
   /* Copy the type.  */
   type = new_binding->type;
   if (LOOKUP_NAMESPACES_ONLY (flags)
-      || (type && hidden_name_p (type) && !(flags & LOOKUP_HIDDEN)))
+      || (type && !(flags & LOOKUP_HIDDEN) && DECL_HIDDEN_P (type)))
     type = NULL_TREE;
 
   /* Copy the value.  */
@@ -4355,7 +4351,7 @@  ambiguous_decl (struct scope_binding *ol
   if (val)
     {
       if (!(flags & LOOKUP_HIDDEN))
-	val = remove_hidden_names (val);
+	val = ovl_skip_hidden (val);
       if (val)
 	switch (TREE_CODE (val))
 	  {
@@ -4465,59 +4461,6 @@  qualify_lookup (tree val, int flags)
   return true;
 }
 
-/* Given a lookup that returned VAL, decide if we want to ignore it or
-   not based on DECL_ANTICIPATED.  */
-
-bool
-hidden_name_p (tree val)
-{
-  if (DECL_P (val)
-      && DECL_LANG_SPECIFIC (val)
-      && TYPE_FUNCTION_OR_TEMPLATE_DECL_P (val)
-      && DECL_ANTICIPATED (val))
-    return true;
-  if (TREE_CODE (val) == OVERLOAD)
-    {
-      for (tree o = val; o; o = OVL_CHAIN (o))
-	if (!hidden_name_p (OVL_FUNCTION (o)))
-	  return false;
-      return true;
-    }
-  return false;
-}
-
-/* Remove any hidden declarations from a possibly overloaded set
-   of functions.  */
-
-tree
-remove_hidden_names (tree fns)
-{
-  if (!fns)
-    return fns;
-
-  if (DECL_P (fns) && hidden_name_p (fns))
-    fns = NULL_TREE;
-  else if (TREE_CODE (fns) == OVERLOAD)
-    {
-      tree o;
-
-      for (o = fns; o; o = OVL_NEXT (o))
-	if (hidden_name_p (OVL_CURRENT (o)))
-	  break;
-      if (o)
-	{
-	  tree n = NULL_TREE;
-
-	  for (o = fns; o; o = OVL_NEXT (o))
-	    if (!hidden_name_p (OVL_CURRENT (o)))
-	      n = lookup_add (OVL_CURRENT (o), n);
-	  fns = n;
-	}
-    }
-
-  return fns;
-}
-
 /* Suggest alternatives for NAME, an IDENTIFIER_NODE for which name
    lookup failed.  Search through all available namespaces and print out
    possible candidates.  If no exact matches are found, and
@@ -5337,10 +5280,6 @@  lookup_name_real_1 (tree name, int prefe
   if (!val)
     val = unqualified_namespace_lookup (name, flags);
 
-  /* Anticipated built-ins and friends aren't found by normal lookup.  */
-  if (val && !(flags & LOOKUP_HIDDEN))
-    val = remove_hidden_names (val);
-
   /* If we have a single function from a using decl, pull it out.  */
   if (val && TREE_CODE (val) == OVERLOAD && !really_overloaded_fn (val))
     val = OVL_FUNCTION (val);
Index: cp/name-lookup.h
===================================================================
--- cp/name-lookup.h	(revision 248422)
+++ cp/name-lookup.h	(working copy)
@@ -308,8 +308,6 @@  extern tree lookup_name_real (tree, int,
 extern tree lookup_type_scope (tree, tag_scope);
 extern tree get_namespace_binding (tree ns, tree id);
 extern void set_global_binding (tree id, tree val);
-extern bool hidden_name_p (tree);
-extern tree remove_hidden_names (tree);
 extern tree lookup_qualified_name (tree, tree, int, bool, /*hidden*/bool = false);
 extern tree lookup_name_nonclass (tree);
 extern tree lookup_name_innermost_nonclass_level (tree);
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 248422)
+++ cp/tree.c	(working copy)
@@ -2204,6 +2204,27 @@  ovl_insert (tree fn, tree maybe_ovl, boo
   return result;
 }
 
+/* Skip any hidden names at the beginning of OVL.   */
+
+tree
+ovl_skip_hidden (tree ovl)
+{
+  for (;
+       ovl && TREE_CODE (ovl) == OVERLOAD && OVL_HIDDEN_P (ovl);
+       ovl = OVL_CHAIN (ovl))
+    gcc_checking_assert (DECL_HIDDEN_P (OVL_FUNCTION (ovl)));
+
+  if (ovl && TREE_CODE (ovl) != OVERLOAD && DECL_HIDDEN_P (ovl))
+    {
+      /* Any hidden functions should have been wrapped in an
+	 overload, but injected friend classes will not.  */
+      gcc_checking_assert (!DECL_DECLARES_FUNCTION_P (ovl));
+      ovl = NULL_TREE;
+    }
+
+  return ovl;
+}
+
 /* NODE is an OVL_HIDDEN_P node which is now revealed.  */
 
 tree