Commit b991151b by Nathan Sidwell Committed by Nathan Sidwell

name-lookup.h (lookup_field_1): Delete.

	* name-lookup.h (lookup_field_1): Delete.
	(get_class_binding_direct, get_class_binding): Add type_or_fns arg.
	* name-lookup.c	(lookup_field_1): make static
	(method_vec_binary_search, method_vec_linear_search): New.  Broken
	out of ...
	(get_class_binding_direct): ... here.  Add TYPE_OR_FNS argument.
	Do complete search of this level.
	(get_class_binding): Adjust.
	* decl.c (reshape_init_class): Call get_class_binding.
	* search.c (lookup_field_r): Move field searching into
	get_class_binding_direct.

From-SVN: r251808
parent ec7f007c
2017-09-06 Nathan Sidwell <nathan@acm.org> 2017-09-06 Nathan Sidwell <nathan@acm.org>
* name-lookup.h (lookup_field_1): Delete.
(get_class_binding_direct, get_class_binding): Add type_or_fns arg.
* name-lookup.c (lookup_field_1): make static
(method_vec_binary_search, method_vec_linear_search): New. Broken
out of ...
(get_class_binding_direct): ... here. Add TYPE_OR_FNS argument.
Do complete search of this level.
(get_class_binding): Adjust.
* decl.c (reshape_init_class): Call get_class_binding.
* search.c (lookup_field_r): Move field searching into
get_class_binding_direct.
* class.c (warn_hidden): Don't barf on non-functions. * class.c (warn_hidden): Don't barf on non-functions.
* decl2.c (check_classfn): Likewise. Check template match earlier. * decl2.c (check_classfn): Likewise. Check template match earlier.
......
...@@ -5746,7 +5746,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p, ...@@ -5746,7 +5746,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
/* We already reshaped this. */ /* We already reshaped this. */
gcc_assert (d->cur->index == field); gcc_assert (d->cur->index == field);
else if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE) else if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
field = lookup_field_1 (type, d->cur->index, /*want_type=*/false); field = get_class_binding (type, d->cur->index, false);
else else
{ {
if (complain & tf_error) if (complain & tf_error)
......
...@@ -1113,79 +1113,54 @@ extract_conversion_operator (tree fns, tree type) ...@@ -1113,79 +1113,54 @@ extract_conversion_operator (tree fns, tree type)
return convs; return convs;
} }
/* TYPE is a class type. Return the member functions in the method /* Binary search of (ordered) METHOD_VEC for NAME. */
vector with name NAME. Does not lazily declare implicitly-declared
member functions. */
tree static tree
get_class_binding_direct (tree type, tree name) method_vec_binary_search (vec<tree, va_gc> *method_vec, tree name)
{ {
vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (type); for (unsigned lo = 0, hi = method_vec->length (); lo < hi;)
if (!method_vec)
return NULL_TREE;
/* Conversion operators can only be found by the marker conversion
operator name. */
bool conv_op = IDENTIFIER_CONV_OP_P (name);
tree lookup = conv_op ? conv_op_identifier : name;
tree val = NULL_TREE;
tree fns;
/* If the type is complete, use binary search. */
if (COMPLETE_TYPE_P (type))
{ {
int lo = 0; unsigned mid = (lo + hi) / 2;
int hi = method_vec->length (); tree binding = (*method_vec)[mid];
while (lo < hi) tree binding_name = OVL_NAME (binding);
{
int i = (lo + hi) / 2;
fns = (*method_vec)[i]; if (binding_name > name)
tree fn_name = OVL_NAME (fns); hi = mid;
if (fn_name > lookup) else if (binding_name < name)
hi = i; lo = mid + 1;
else if (fn_name < lookup) else
lo = i + 1; return binding;
else
{
val = fns;
break;
}
}
} }
else
for (int i = 0; vec_safe_iterate (method_vec, i, &fns); ++i)
/* We can get a NULL binding during insertion of a new
method name, because the identifier_binding machinery
performs a lookup. If we find such a NULL slot, that's
the thing we were looking for, so we might as well bail
out immediately. */
if (!fns)
break;
else if (OVL_NAME (fns) == lookup)
{
val = fns;
break;
}
/* Extract the conversion operators asked for, unless the general return NULL_TREE;
conversion operator was requested. */ }
if (val && conv_op)
{
gcc_checking_assert (OVL_FUNCTION (val) == conv_op_marker);
val = OVL_CHAIN (val);
if (tree type = TREE_TYPE (name))
val = extract_conversion_operator (val, type);
}
return val; /* Linear search of (unordered) METHOD_VEC for NAME. */
static tree
method_vec_linear_search (vec<tree, va_gc> *method_vec, tree name)
{
for (int ix = method_vec->length (); ix--;)
/* We can get a NULL binding during insertion of a new method
name, because the identifier_binding machinery performs a
lookup. If we find such a NULL slot, that's the thing we were
looking for, so we might as well bail out immediately. */
if (tree binding = (*method_vec)[ix])
{
if (OVL_NAME (binding) == name)
return binding;
}
else
break;
return NULL_TREE;
} }
/* Do a 1-level search for NAME as a member of TYPE. The caller must /* Do a 1-level search for NAME as a member of TYPE. The caller must
figure out whether it can access this field. (Since it is only one figure out whether it can access this field. (Since it is only one
level, this is reasonable.) */ level, this is reasonable.) */
tree static tree
lookup_field_1 (tree type, tree name, bool want_type) lookup_field_1 (tree type, tree name, bool want_type)
{ {
tree field; tree field;
...@@ -1281,11 +1256,62 @@ lookup_field_1 (tree type, tree name, bool want_type) ...@@ -1281,11 +1256,62 @@ lookup_field_1 (tree type, tree name, bool want_type)
return NULL_TREE; return NULL_TREE;
} }
/* TYPE is a class type. Return the overloads in /* Look for NAME as an immediate member of KLASS (including
the method vector with name NAME. Lazily create ctors etc. */ anon-members or unscoped enum member). TYPE_OR_FNS is zero for
regular search. >0 to get a type binding (if there is one) and <0
if you want (just) the member function binding.
Use this if you do not want lazy member creation. */
tree
get_class_binding_direct (tree klass, tree name, int type_or_fns)
{
gcc_checking_assert (RECORD_OR_UNION_TYPE_P (klass));
/* Conversion operators can only be found by the marker conversion
operator name. */
bool conv_op = IDENTIFIER_CONV_OP_P (name);
tree lookup = conv_op ? conv_op_identifier : name;
tree val = NULL_TREE;
if (type_or_fns > 0)
/* User wants type. Don't look in method_vec. */;
else if (vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (klass))
{
if (COMPLETE_TYPE_P (klass))
val = method_vec_binary_search (method_vec, lookup);
else
val = method_vec_linear_search (method_vec, lookup);
}
if (type_or_fns < 0)
/* User wants functions. Don't look for a field. */;
else if (!val || (TREE_CODE (val) == OVERLOAD && OVL_USING_P (val)))
/* Dependent using declarations are a 'field', make sure we
return that even if we saw an overload already. */
if (tree field_val = lookup_field_1 (klass, lookup, type_or_fns > 0))
if (!val || TREE_CODE (field_val) == USING_DECL)
val = field_val;
/* Extract the conversion operators asked for, unless the general
conversion operator was requested. */
if (val && conv_op)
{
gcc_checking_assert (OVL_FUNCTION (val) == conv_op_marker);
val = OVL_CHAIN (val);
if (tree type = TREE_TYPE (name))
val = extract_conversion_operator (val, type);
}
return val;
}
/* Look for NAME's binding in exactly KLASS. See
get_class_binding_direct for argument description. Does lazy
special function creation as necessary. */
tree tree
get_class_binding (tree type, tree name) get_class_binding (tree type, tree name, int type_or_fns)
{ {
type = complete_type (type); type = complete_type (type);
...@@ -1314,7 +1340,7 @@ get_class_binding (tree type, tree name) ...@@ -1314,7 +1340,7 @@ get_class_binding (tree type, tree name)
} }
} }
return get_class_binding_direct (type, name); return get_class_binding_direct (type, name, type_or_fns);
} }
/* Find the slot containing overloads called 'NAME'. If there is no /* Find the slot containing overloads called 'NAME'. If there is no
......
...@@ -319,9 +319,8 @@ extern void pop_decl_namespace (void); ...@@ -319,9 +319,8 @@ extern void pop_decl_namespace (void);
extern void do_namespace_alias (tree, tree); extern void do_namespace_alias (tree, tree);
extern tree do_class_using_decl (tree, tree); extern tree do_class_using_decl (tree, tree);
extern tree lookup_arg_dependent (tree, tree, vec<tree, va_gc> *); extern tree lookup_arg_dependent (tree, tree, vec<tree, va_gc> *);
extern tree lookup_field_1 (tree, tree, bool); extern tree get_class_binding_direct (tree, tree, int type_or_fns = -1);
extern tree get_class_binding_direct (tree, tree); extern tree get_class_binding (tree, tree, int type_or_fns = -1);
extern tree get_class_binding (tree, tree);
extern tree *get_method_slot (tree klass, tree name); extern tree *get_method_slot (tree klass, tree name);
extern void resort_type_method_vec (void *, void *, extern void resort_type_method_vec (void *, void *,
gt_pointer_operator, void *); gt_pointer_operator, void *);
......
...@@ -974,23 +974,7 @@ lookup_field_r (tree binfo, void *data) ...@@ -974,23 +974,7 @@ lookup_field_r (tree binfo, void *data)
&& !BINFO_VIRTUAL_P (binfo)) && !BINFO_VIRTUAL_P (binfo))
return dfs_skip_bases; return dfs_skip_bases;
/* First, look for a function. There can't be a function and a data nval = get_class_binding (type, lfi->name, lfi->want_type);
member with the same name, and if there's a function and a type
with the same name, the type is hidden by the function. */
if (!lfi->want_type)
nval = get_class_binding (type, lfi->name);
if (!nval)
/* Look for a data member or type. */
nval = lookup_field_1 (type, lfi->name, lfi->want_type);
else if (TREE_CODE (nval) == OVERLOAD && OVL_USING_P (nval))
{
/* If we have both dependent and non-dependent using-declarations, return
the dependent one rather than an incomplete list of functions. */
tree dep_using = lookup_field_1 (type, lfi->name, lfi->want_type);
if (dep_using && TREE_CODE (dep_using) == USING_DECL)
nval = dep_using;
}
/* If we're looking up a type (as with an elaborated type specifier) /* If we're looking up a type (as with an elaborated type specifier)
we ignore all non-types we find. */ we ignore all non-types we find. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment