OSDN Git Service

Speed up Koenig lookup.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 14 Aug 1999 11:08:53 +0000 (11:08 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 14 Aug 1999 11:08:53 +0000 (11:08 +0000)
* decl.c (unqualified_namespace_lookup): Nonstatic.  Add spacep parm
to return namespaces we've looked at.
* decl2.c (lookup_using_namespace): Likewise.
(add_function): Don't call ovl_member.
(lookup_arg_dependent): Initialize k.namespaces to the list of
namespaces seen in unqualified lookup.
* call.c (equal_functions): Move here from tree.c.
(joust): Use it to handle duplicate candidates.
* tree.c (ovl_member): Use ==.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@28710 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/lex.c
gcc/cp/tree.c

index 4b882a6..b5ce289 100644 (file)
@@ -1,3 +1,16 @@
+1999-08-14  Jason Merrill  <jason@yorick.cygnus.com>
+
+       Speed up Koenig lookup.
+       * decl.c (unqualified_namespace_lookup): Nonstatic.  Add spacep parm
+       to return namespaces we've looked at.
+       * decl2.c (lookup_using_namespace): Likewise.
+       (add_function): Don't call ovl_member.
+       (lookup_arg_dependent): Initialize k.namespaces to the list of 
+       namespaces seen in unqualified lookup.
+       * call.c (equal_functions): Move here from tree.c.
+       (joust): Use it to handle duplicate candidates.
+       * tree.c (ovl_member): Use ==.
+
 1999-08-13  Mark Mitchell  <mark@codesourcery.com>
 
        * cp-tree.def (DECL_STMT): Make it smaller.
index fda38de..f193a4b 100644 (file)
@@ -44,6 +44,7 @@ static tree build_new_method_call PROTO((tree, tree, tree, tree, int));
 
 static tree build_field_call PROTO((tree, tree, tree, tree));
 static struct z_candidate * tourney PROTO((struct z_candidate *));
+static int equal_functions PROTO((tree, tree));
 static int joust PROTO((struct z_candidate *, struct z_candidate *, int));
 static int compare_ics PROTO((tree, tree));
 static tree build_over_call PROTO((struct z_candidate *, tree, int));
@@ -4768,6 +4769,20 @@ add_warning (winner, loser)
                                     winner->warnings);
 }
 
+/* Returns true iff functions are equivalent. Equivalent functions are
+   not identical only if one is a function-local extern function.
+   This assumes that function-locals don't have TREE_PERMANENT.  */
+
+static inline int
+equal_functions (fn1, fn2)
+     tree fn1;
+     tree fn2;
+{
+  if (!TREE_PERMANENT (fn1) || !TREE_PERMANENT (fn2))
+    return decls_match (fn1, fn2);
+  return fn1 == fn2;
+}
+
 /* Compare two candidates for overloading as described in
    [over.match.best].  Return values:
 
@@ -4963,6 +4978,12 @@ joust (cand1, cand2, warn)
        }
     }
 
+  /* If the two functions are the same (this can happen with declarations
+     in multiple scopes and arg-dependent lookup), arbitrarily choose one.  */
+  if (DECL_P (cand1->fn) && DECL_P (cand2->fn)
+      && equal_functions (cand1->fn, cand2->fn))
+    return 1;
+
 tweak:
 
   /* Extension: If the worst conversion for one candidate is worse than the
index 410dc7a..82022fa 100644 (file)
@@ -2886,8 +2886,9 @@ extern tree lookup_name_namespace_only          PROTO((tree));
 extern void begin_only_namespace_names          PROTO((void));
 extern void end_only_namespace_names            PROTO((void));
 extern tree namespace_ancestor                 PROTO((tree, tree));
-extern int  lookup_using_namespace              PROTO((tree,tree,tree,tree,int));
-extern int  qualified_lookup_using_namespace    PROTO((tree,tree,tree,int));
+extern tree unqualified_namespace_lookup       PROTO((tree, int, tree *));
+extern int  lookup_using_namespace              PROTO((tree, tree, tree, tree, int, tree *));
+extern int  qualified_lookup_using_namespace    PROTO((tree, tree, tree, int));
 extern tree auto_function                      PROTO((tree, tree, enum built_in_function));
 extern void init_decl_processing               PROTO((void));
 extern int init_type_desc                      PROTO((void));
index 8c96020..6fb61f7 100644 (file)
@@ -179,7 +179,6 @@ static void pop_binding PROTO((tree, tree));
 static tree local_variable_p PROTO((tree));
 static tree find_binding PROTO((tree, tree));
 static tree select_decl PROTO((tree, int));
-static tree unqualified_namespace_lookup PROTO((tree, int));
 static int lookup_flags PROTO((int, int));
 static tree qualify_lookup PROTO((tree, int));
 static tree record_builtin_java_type PROTO((const char *, int));
@@ -5557,13 +5556,15 @@ select_decl (binding, flags)
   return val;
 }
 
-/* Unscoped lookup of a global, iterate over namespaces, considering
-   using namespace statements. */
+/* Unscoped lookup of a global: iterate over current namespaces,
+   considering using-directives.  If SPACESP is non-NULL, store a list
+   of the namespaces we've considered in it.  */
 
-static tree
-unqualified_namespace_lookup (name, flags)
+tree
+unqualified_namespace_lookup (name, flags, spacesp)
      tree name;
      int flags;
+     tree *spacesp;
 {
   struct tree_binding _binding;
   tree b = binding_init (&_binding);
@@ -5573,8 +5574,13 @@ unqualified_namespace_lookup (name, flags)
   struct binding_level *level;
   tree val = NULL_TREE;
 
-  while (!val)
+  if (spacesp)
+    *spacesp = NULL_TREE;
+
+  for (; !val; scope = CP_DECL_CONTEXT (scope))
     {
+      if (spacesp)
+       *spacesp = scratch_tree_cons (scope, NULL_TREE, *spacesp);
       val = binding_for_name (name, scope);
 
       /* Initialize binding for this context. */
@@ -5586,7 +5592,7 @@ unqualified_namespace_lookup (name, flags)
           !level->namespace_p;
           level = level->level_chain)
        if (!lookup_using_namespace (name, b, level->using_directives,
-                                     scope, flags))
+                                     scope, flags, spacesp))
          /* Give up because of error. */
          return error_mark_node;
 
@@ -5596,7 +5602,7 @@ unqualified_namespace_lookup (name, flags)
       while (1)
        {
          if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter), 
-                                      scope, flags))
+                                      scope, flags, spacesp))
            /* Give up because of error. */
            return error_mark_node;
          if (siter == scope) break;
@@ -5606,7 +5612,6 @@ unqualified_namespace_lookup (name, flags)
       val = select_decl (b, flags);
       if (scope == global_namespace)
        break;
-      scope = CP_DECL_CONTEXT (scope);
     }
   return val;
 }
@@ -5811,7 +5816,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
   /* Now lookup in namespace scopes.  */
   if (!val || val_is_implicit_typename)
     {
-      t = unqualified_namespace_lookup (name, flags);
+      t = unqualified_namespace_lookup (name, flags, 0);
       if (t)
        {
          if (val_is_implicit_typename && !yylex)
index 3cebe81..ab82a8e 100644 (file)
@@ -4349,14 +4349,18 @@ ambiguous_decl (name, old, new, flags)
   return old;
 }
 
-/* Add the bindings of name in used namespaces to val.
-   The using list is defined by usings, and the lookup goes to scope.
+/* Subroutine of unualified_namespace_lookup:
+   Add the bindings of NAME in used namespaces to VAL.
+   We are currently looking for names in namespace SCOPE, so we
+   look through USINGS for using-directives of namespaces
+   which have SCOPE as a common ancestor with the current scope.
    Returns zero on errors. */
 
 int
-lookup_using_namespace (name, val, usings, scope, flags)
+lookup_using_namespace (name, val, usings, scope, flags, spacesp)
      tree name, val, usings, scope;
      int flags;
+     tree *spacesp;
 {
   tree iter;
   tree val1;
@@ -4365,6 +4369,9 @@ lookup_using_namespace (name, val, usings, scope, flags)
   for (iter = usings; iter; iter = TREE_CHAIN (iter))
     if (TREE_VALUE (iter) == scope)
       {
+       if (spacesp)
+         *spacesp = scratch_tree_cons (TREE_PURPOSE (iter), NULL_TREE,
+                                       *spacesp);
        val1 = binding_for_name (name, TREE_PURPOSE (iter));
        /* Resolve ambiguities. */
        val = ambiguous_decl (name, val, val1, flags);
@@ -4573,28 +4580,32 @@ add_function (k, fn)
      struct arg_lookup *k;
      tree fn;
 {
-  if (ovl_member (fn, k->functions))
-    return 0;
+  /* We used to check here to see if the function was already in the list,
+     but that's O(n^2), which is just too expensive for function lookup.
+     Now we deal with the occasional duplicate in joust.  In doing this, we
+     assume that the number of duplicates will be small compared to the
+     total number of functions being compared, which should usually be the
+     case.  */
+
   /* We must find only functions, or exactly one non-function. */
   if (k->functions && is_overloaded_fn (k->functions)
       && is_overloaded_fn (fn))
     k->functions = build_overload (fn, k->functions);
-  else 
-    if(k->functions)
-      {
-       tree f1 = OVL_CURRENT (k->functions);
-       tree f2 = fn;
-       if (is_overloaded_fn (f1))
-         {
-           fn = f1; f1 = f2; f2 = fn;
-         }
-       cp_error_at ("`%D' is not a function,", f1);
-       cp_error_at ("  conflict with `%D'", f2);
-       cp_error ("  in call to `%D'", k->name);
-       return 1;
-      }
-    else
-      k->functions = fn;
+  else if (k->functions)
+    {
+      tree f1 = OVL_CURRENT (k->functions);
+      tree f2 = fn;
+      if (is_overloaded_fn (f1))
+       {
+         fn = f1; f1 = f2; f2 = fn;
+       }
+      cp_error_at ("`%D' is not a function,", f1);
+      cp_error_at ("  conflict with `%D'", f2);
+      cp_error ("  in call to `%D'", k->name);
+      return 1;
+    }
+  else
+    k->functions = fn;
   return 0;
 }
 
@@ -4615,7 +4626,7 @@ arg_assoc_namespace (k, scope)
   value = namespace_binding (k->name, scope);
   if (!value)
     return 0;
-  
+
   for (; value; value = OVL_NEXT (value))
     if (add_function (k, OVL_CURRENT (value)))
       return 1;
@@ -4845,11 +4856,18 @@ lookup_arg_dependent (name, fns, args)
      tree args;
 {
   struct arg_lookup k;
+
   k.name = name;
   k.functions = fns;
-  k.namespaces = NULL_TREE;
   k.classes = NULL_TREE;
-  
+
+  /* Note that we've already looked at some namespaces during normal
+     unqualified lookup, unless we found a decl in function scope.  */
+  if (fns && ! TREE_PERMANENT (OVL_CURRENT (fns)))
+    k.namespaces = NULL_TREE;
+  else
+    unqualified_namespace_lookup (name, 0, &k.namespaces);
+
   push_scratch_obstack ();
   arg_assoc_args (&k, args);
   pop_obstacks ();
index f36da53..c28bba0 100644 (file)
@@ -3078,10 +3078,13 @@ do_identifier (token, parsing, args)
     id = lastiddecl;
 
   /* Do Koenig lookup if appropriate (inside templates we build lookup
-     expressions instead).  */
+     expressions instead).
+
+     [basic.lookup.koenig]: If the ordinary unqualified lookup of the name
+     finds the declaration of a class member function, the associated
+     namespaces and classes are not considered.  */
+
   if (args && !current_template_parms && (!id || is_global (id)))
-    /* If we have arguments and we only found global names, do Koenig
-       lookup. */
     id = lookup_arg_dependent (token, id, args);
 
   /* Remember that this name has been used in the class definition, as per
index 7a35b47..f2e8257 100644 (file)
@@ -37,7 +37,6 @@ static tree list_hash_lookup PROTO((int, tree, tree, tree));
 static void propagate_binfo_offsets PROTO((tree, tree));
 static int avoid_overlap PROTO((tree, tree));
 static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
-static int equal_functions PROTO((tree, tree));
 static tree no_linkage_helper PROTO((tree));
 static tree build_srcloc PROTO((char *, int));
 
@@ -1411,20 +1410,6 @@ build_overload (decl, chain)
   return ovl_cons (decl, chain);
 }
 
-/* Returns true iff functions are equivalent. Equivalent functions are
-   not identical only if one is a function-local extern function.
-   This assumes that function-locals don't have TREE_PERMANENT.  */
-
-static int
-equal_functions (fn1, fn2)
-     tree fn1;
-     tree fn2;
-{
-  if (!TREE_PERMANENT (fn1) || !TREE_PERMANENT (fn2))
-    return decls_match (fn1, fn2);
-  return fn1 == fn2;
-}
-
 /* True if fn is in ovl. */
 
 int
@@ -1435,9 +1420,9 @@ ovl_member (fn, ovl)
   if (ovl == NULL_TREE)
     return 0;
   if (TREE_CODE (ovl) != OVERLOAD)
-    return equal_functions (ovl, fn);
+    return ovl == fn;
   for (; ovl; ovl = OVL_CHAIN (ovl))
-    if (equal_functions (OVL_FUNCTION (ovl), fn))
+    if (OVL_FUNCTION (ovl) == fn)
       return 1;
   return 0;
 }