mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-09 17:11:20 +08:00
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 ==. From-SVN: r28710
This commit is contained in:
parent
9188c36364
commit
2c169babb6
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
|
@ -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 ();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user