+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.
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));
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:
}
}
+ /* 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
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));
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));
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);
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. */
!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;
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;
val = select_decl (b, flags);
if (scope == global_namespace)
break;
- scope = CP_DECL_CONTEXT (scope);
}
return val;
}
/* 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)
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;
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);
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;
}
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;
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 ();
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
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));
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
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;
}