Commit 2e12a855 by Nathan Sidwell Committed by Nathan Sidwell

Conversion operators kept on single overload set

	Conversion operators kept on single overload set
	* class.c (add_method): Keep all conv-ops on one slot.
	* name-lookup.c (lookup_conversion_operator): Pull the desired
	conv op out of overload set.
	* search.c (lookup_conversions_r): Lose template/non-template
	distinction.
	(lookup_conversions): Likewise.

From-SVN: r251340
parent 281de9c2
2017-08-24 Nathan Sidwell <nathan@acm.org>
Conversion operators kept on single overload set
* class.c (add_method): Keep all conv-ops on one slot.
* name-lookup.c (lookup_conversion_operator): Pull the desired
conv op out of overload set.
* search.c (lookup_conversions_r): Lose template/non-template
distinction.
(lookup_conversions): Likewise.
2017-08-23 Nathan Sidwell <nathan@acm.org> 2017-08-23 Nathan Sidwell <nathan@acm.org>
* cp-tree.h (lookup_field_1, lookup_fnfields_slot, * cp-tree.h (lookup_field_1, lookup_fnfields_slot,
......
...@@ -1014,30 +1014,16 @@ modify_vtable_entry (tree t, ...@@ -1014,30 +1014,16 @@ modify_vtable_entry (tree t,
bool bool
add_method (tree type, tree method, bool via_using) add_method (tree type, tree method, bool via_using)
{ {
unsigned slot;
bool template_conv_p = false;
bool conv_p;
vec<tree, va_gc> *method_vec;
bool complete_p;
bool insert_p = false;
tree current_fns;
if (method == error_mark_node) if (method == error_mark_node)
return false; return false;
complete_p = COMPLETE_TYPE_P (type); bool complete_p = COMPLETE_TYPE_P (type);
conv_p = DECL_CONV_FN_P (method); bool conv_p = DECL_CONV_FN_P (method);
if (conv_p)
template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
&& DECL_TEMPLATE_CONV_FN_P (method));
method_vec = CLASSTYPE_METHOD_VEC (type); vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (type);
if (!method_vec) if (!method_vec)
{ {
/* Make a new method vector. We start with 8 entries. We must /* Make a new method vector. We start with 8 entries. */
allocate at least two (for constructors and destructors), and
we're going to end up with an assignment operator at some
point as well. */
vec_alloc (method_vec, 8); vec_alloc (method_vec, 8);
CLASSTYPE_METHOD_VEC (type) = method_vec; CLASSTYPE_METHOD_VEC (type) = method_vec;
} }
...@@ -1045,24 +1031,22 @@ add_method (tree type, tree method, bool via_using) ...@@ -1045,24 +1031,22 @@ add_method (tree type, tree method, bool via_using)
/* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */ /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */
grok_special_member_properties (method); grok_special_member_properties (method);
bool insert_p = true;
unsigned slot;
tree m; tree m;
insert_p = true;
/* See if we already have an entry with this name. */ /* See if we already have an entry with this name. */
for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
vec_safe_iterate (method_vec, slot, &m); vec_safe_iterate (method_vec, slot, &m);
++slot) ++slot)
{ {
m = OVL_FIRST (m); m = OVL_FIRST (m);
if (template_conv_p) if (conv_p)
{ {
if (TREE_CODE (m) == TEMPLATE_DECL if (DECL_CONV_FN_P (m))
&& DECL_TEMPLATE_CONV_FN_P (m))
insert_p = false; insert_p = false;
break; break;
} }
if (conv_p && !DECL_CONV_FN_P (m))
break;
if (DECL_NAME (m) == DECL_NAME (method)) if (DECL_NAME (m) == DECL_NAME (method))
{ {
insert_p = false; insert_p = false;
...@@ -1073,7 +1057,8 @@ add_method (tree type, tree method, bool via_using) ...@@ -1073,7 +1057,8 @@ add_method (tree type, tree method, bool via_using)
&& DECL_NAME (m) > DECL_NAME (method)) && DECL_NAME (m) > DECL_NAME (method))
break; break;
} }
current_fns = insert_p ? NULL_TREE : (*method_vec)[slot]; tree current_fns = insert_p ? NULL_TREE : (*method_vec)[slot];
gcc_assert (!DECL_EXTERN_C_P (method));
/* Check to see if we've already got this method. */ /* Check to see if we've already got this method. */
for (ovl_iterator iter (current_fns); iter; ++iter) for (ovl_iterator iter (current_fns); iter; ++iter)
...@@ -1216,8 +1201,7 @@ add_method (tree type, tree method, bool via_using) ...@@ -1216,8 +1201,7 @@ add_method (tree type, tree method, bool via_using)
} }
/* A class should never have more than one destructor. */ /* A class should never have more than one destructor. */
if (current_fns && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method)) gcc_assert (!current_fns || !DECL_DESTRUCTOR_P (method));
return false;
current_fns = ovl_insert (method, current_fns, via_using); current_fns = ovl_insert (method, current_fns, via_using);
......
...@@ -1096,34 +1096,31 @@ lookup_arg_dependent (tree name, tree fns, vec<tree, va_gc> *args) ...@@ -1096,34 +1096,31 @@ lookup_arg_dependent (tree name, tree fns, vec<tree, va_gc> *args)
static tree static tree
lookup_conversion_operator (tree class_type, tree type) lookup_conversion_operator (tree class_type, tree type)
{ {
tree tpls = NULL_TREE; tree convs = NULL_TREE;
if (TYPE_HAS_CONVERSION (class_type)) if (TYPE_HAS_CONVERSION (class_type))
{ {
tree fns; tree fns = NULL_TREE;
tree tpls = NULL_TREE;
vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (class_type); vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (class_type);
for (int i = CLASSTYPE_FIRST_CONVERSION_SLOT; vec_safe_iterate (methods, CLASSTYPE_FIRST_CONVERSION_SLOT, &fns);
vec_safe_iterate (methods, i, &fns); ++i) if (fns && !DECL_CONV_FN_P (OVL_FIRST (fns)))
fns = NULL_TREE;
for (ovl_iterator iter (fns); iter; ++iter)
{ {
/* All the conversion operators come near the beginning of if (same_type_p (DECL_CONV_FN_TYPE (*iter), type))
the class. Therefore, if FN is not a conversion convs = lookup_add (*iter, convs);
operator, there is no matching conversion operator in
CLASS_TYPE. */
tree fn = OVL_FIRST (fns);
if (!DECL_CONV_FN_P (fn))
break;
if (TREE_CODE (fn) == TEMPLATE_DECL) if (TREE_CODE (*iter) == TEMPLATE_DECL)
/* All the templated conversion functions are on the same tpls = lookup_add (*iter, tpls);
slot, so remember it. */
tpls = fns;
else if (same_type_p (DECL_CONV_FN_TYPE (fn), type))
return fns;
} }
if (!convs)
convs = tpls;
} }
return tpls; return convs;
} }
/* TYPE is a class type. Return the member functions in the method /* TYPE is a class type. Return the member functions in the method
......
...@@ -38,8 +38,7 @@ static tree dfs_dcast_hint_post (tree, void *); ...@@ -38,8 +38,7 @@ static tree dfs_dcast_hint_post (tree, void *);
static tree dfs_debug_mark (tree, void *); static tree dfs_debug_mark (tree, void *);
static int check_hidden_convs (tree, int, int, tree, tree, tree); static int check_hidden_convs (tree, int, int, tree, tree, tree);
static tree split_conversions (tree, tree, tree, tree); static tree split_conversions (tree, tree, tree, tree);
static int lookup_conversions_r (tree, int, int, static int lookup_conversions_r (tree, int, int, tree, tree, tree *);
tree, tree, tree, tree, tree *, tree *);
static int look_for_overrides_r (tree, tree); static int look_for_overrides_r (tree, tree);
static tree lookup_field_r (tree, void *); static tree lookup_field_r (tree, void *);
static tree dfs_accessible_post (tree, void *); static tree dfs_accessible_post (tree, void *);
...@@ -2333,14 +2332,13 @@ split_conversions (tree my_convs, tree parent_convs, ...@@ -2333,14 +2332,13 @@ split_conversions (tree my_convs, tree parent_convs,
} }
/* Worker for lookup_conversions. Lookup conversion functions in /* Worker for lookup_conversions. Lookup conversion functions in
BINFO and its children. VIRTUAL_DEPTH is nonzero, if BINFO is in BINFO and its children. VIRTUAL_DEPTH is nonzero, if BINFO is in a
a morally virtual base, and VIRTUALNESS is nonzero, if we've morally virtual base, and VIRTUALNESS is nonzero, if we've
encountered virtual bases already in the tree walk. PARENT_CONVS & encountered virtual bases already in the tree walk. PARENT_CONVS
PARENT_TPL_CONVS are lists of list of conversions within parent is a list of conversions within parent binfos. OTHER_CONVS are
binfos. OTHER_CONVS and OTHER_TPL_CONVS are conversions found conversions found elsewhere in the tree. Return the conversions
elsewhere in the tree. Return the conversions found within this found within this portion of the graph in CONVS. Return nonzero if
portion of the graph in CONVS and TPL_CONVS. Return nonzero is we we encountered virtualness. We keep template and non-template
encountered virtualness. We keep template and non-template
conversions separate, to avoid unnecessary type comparisons. conversions separate, to avoid unnecessary type comparisons.
The located conversion functions are held in lists of lists. The The located conversion functions are held in lists of lists. The
...@@ -2353,26 +2351,17 @@ split_conversions (tree my_convs, tree parent_convs, ...@@ -2353,26 +2351,17 @@ split_conversions (tree my_convs, tree parent_convs,
is the converted-to type. */ is the converted-to type. */
static int static int
lookup_conversions_r (tree binfo, lookup_conversions_r (tree binfo, int virtual_depth, int virtualness,
int virtual_depth, int virtualness, tree parent_convs, tree other_convs, tree *convs)
tree parent_convs, tree parent_tpl_convs,
tree other_convs, tree other_tpl_convs,
tree *convs, tree *tpl_convs)
{ {
int my_virtualness = 0; int my_virtualness = 0;
tree my_convs = NULL_TREE; tree my_convs = NULL_TREE;
tree my_tpl_convs = NULL_TREE;
tree child_convs = NULL_TREE; tree child_convs = NULL_TREE;
tree child_tpl_convs = NULL_TREE;
unsigned i;
tree base_binfo;
vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
tree conv;
/* If we have no conversion operators, then don't look. */ /* If we have no conversion operators, then don't look. */
if (!TYPE_HAS_CONVERSION (BINFO_TYPE (binfo))) if (!TYPE_HAS_CONVERSION (BINFO_TYPE (binfo)))
{ {
*convs = *tpl_convs = NULL_TREE; *convs = NULL_TREE;
return 0; return 0;
} }
...@@ -2381,60 +2370,32 @@ lookup_conversions_r (tree binfo, ...@@ -2381,60 +2370,32 @@ lookup_conversions_r (tree binfo,
virtual_depth++; virtual_depth++;
/* First, locate the unhidden ones at this level. */ /* First, locate the unhidden ones at this level. */
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
vec_safe_iterate (method_vec, i, &conv); tree conv = NULL_TREE;
++i) vec_safe_iterate (method_vec, CLASSTYPE_FIRST_CONVERSION_SLOT, &conv);
{ if (conv && !DECL_CONV_FN_P (OVL_FIRST (conv)))
tree cur = OVL_FIRST (conv); conv = NULL_TREE;
if (!DECL_CONV_FN_P (cur))
break;
if (TREE_CODE (cur) == TEMPLATE_DECL) for (ovl_iterator iter (conv); iter; ++iter)
/* Only template conversions can be overloaded, and we must {
flatten them out and check each one individually. */ tree fn = *iter;
for (ovl_iterator iter (conv); iter; ++iter) tree type = DECL_CONV_FN_TYPE (fn);
{
tree tpl = *iter;
tree type = DECL_CONV_FN_TYPE (tpl);
if (check_hidden_convs (binfo, virtual_depth, virtualness, if (TREE_CODE (fn) != TEMPLATE_DECL && type_uses_auto (type))
type, parent_tpl_convs, other_tpl_convs))
{
my_tpl_convs = tree_cons (binfo, tpl, my_tpl_convs);
TREE_TYPE (my_tpl_convs) = type;
if (virtual_depth)
{
TREE_STATIC (my_tpl_convs) = 1;
my_virtualness = 1;
}
}
}
else
{ {
tree name = DECL_NAME (cur); mark_used (fn);
type = DECL_CONV_FN_TYPE (fn);
}
if (!IDENTIFIER_MARKED (name)) if (check_hidden_convs (binfo, virtual_depth, virtualness,
type, parent_convs, other_convs))
{
my_convs = tree_cons (binfo, fn, my_convs);
TREE_TYPE (my_convs) = type;
if (virtual_depth)
{ {
tree type = DECL_CONV_FN_TYPE (cur); TREE_STATIC (my_convs) = 1;
if (type_uses_auto (type)) my_virtualness = 1;
{
mark_used (cur);
type = DECL_CONV_FN_TYPE (cur);
}
if (check_hidden_convs (binfo, virtual_depth, virtualness,
type, parent_convs, other_convs))
{
my_convs = tree_cons (binfo, conv, my_convs);
TREE_TYPE (my_convs) = type;
if (virtual_depth)
{
TREE_STATIC (my_convs) = 1;
my_virtualness = 1;
}
IDENTIFIER_MARKED (name) = 1;
}
} }
} }
} }
...@@ -2446,41 +2407,27 @@ lookup_conversions_r (tree binfo, ...@@ -2446,41 +2407,27 @@ lookup_conversions_r (tree binfo,
TREE_STATIC (parent_convs) = 1; TREE_STATIC (parent_convs) = 1;
} }
if (my_tpl_convs)
{
parent_tpl_convs = tree_cons (binfo, my_tpl_convs, parent_tpl_convs);
if (virtual_depth)
TREE_STATIC (parent_tpl_convs) = 1;
}
child_convs = other_convs; child_convs = other_convs;
child_tpl_convs = other_tpl_convs;
/* Now iterate over each base, looking for more conversions. */ /* Now iterate over each base, looking for more conversions. */
unsigned i;
tree base_binfo;
for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{ {
tree base_convs, base_tpl_convs; tree base_convs;
unsigned base_virtualness; unsigned base_virtualness;
base_virtualness = lookup_conversions_r (base_binfo, base_virtualness = lookup_conversions_r (base_binfo,
virtual_depth, virtualness, virtual_depth, virtualness,
parent_convs, parent_tpl_convs, parent_convs, child_convs,
child_convs, child_tpl_convs, &base_convs);
&base_convs, &base_tpl_convs);
if (base_virtualness) if (base_virtualness)
my_virtualness = virtualness = 1; my_virtualness = virtualness = 1;
child_convs = chainon (base_convs, child_convs); child_convs = chainon (base_convs, child_convs);
child_tpl_convs = chainon (base_tpl_convs, child_tpl_convs);
} }
/* Unmark the conversions found at this level */
for (conv = my_convs; conv; conv = TREE_CHAIN (conv))
IDENTIFIER_MARKED (OVL_NAME (TREE_VALUE (conv))) = 0;
*convs = split_conversions (my_convs, parent_convs, *convs = split_conversions (my_convs, parent_convs,
child_convs, other_convs); child_convs, other_convs);
*tpl_convs = split_conversions (my_tpl_convs, parent_tpl_convs,
child_tpl_convs, other_tpl_convs);
return my_virtualness; return my_virtualness;
} }
...@@ -2497,17 +2444,16 @@ lookup_conversions_r (tree binfo, ...@@ -2497,17 +2444,16 @@ lookup_conversions_r (tree binfo,
tree tree
lookup_conversions (tree type) lookup_conversions (tree type)
{ {
tree convs, tpl_convs; tree convs;
tree list = NULL_TREE;
complete_type (type); complete_type (type);
if (!CLASS_TYPE_P (type) || !TYPE_BINFO (type)) if (!CLASS_TYPE_P (type) || !TYPE_BINFO (type))
return NULL_TREE; return NULL_TREE;
lookup_conversions_r (TYPE_BINFO (type), 0, 0, lookup_conversions_r (TYPE_BINFO (type), 0, 0, NULL_TREE, NULL_TREE, &convs);
NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,
&convs, &tpl_convs);
tree list = NULL_TREE;
/* Flatten the list-of-lists */ /* Flatten the list-of-lists */
for (; convs; convs = TREE_CHAIN (convs)) for (; convs; convs = TREE_CHAIN (convs))
{ {
...@@ -2522,19 +2468,6 @@ lookup_conversions (tree type) ...@@ -2522,19 +2468,6 @@ lookup_conversions (tree type)
} }
} }
for (; tpl_convs; tpl_convs = TREE_CHAIN (tpl_convs))
{
tree probe, next;
for (probe = TREE_VALUE (tpl_convs); probe; probe = next)
{
next = TREE_CHAIN (probe);
TREE_CHAIN (probe) = list;
list = probe;
}
}
return list; return list;
} }
......
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