Commit fcaf3065 by Nathan Sidwell Committed by Nathan Sidwell

class.c (add_method): Move slot search and insertion to ...

	* class.c (add_method): Move slot search and insertion to ...
	* name-lookup.c (get_method_slot): ... this new function.
	(lookup_fnfields_slot_nolazy): Cope with NULL slot.
	* name-lookup.h (get_method_slot): Declare.
	* decl.c (cxx_init_decl_processinng): Give conv_op_marker a more
	realistic type.
	(grok_special_member_properties): Set
	TYPE_HAS_CONVERSION. Expicitly look at DECL_NAME for specialness.
	Improve TYPE_HAS_CONSTEXPR_CTOR setting.

From-SVN: r251737
parent 146c2e3a
2017-09-05 Nathan Sidwell <nathan@acm.org>
* class.c (add_method): Move slot search and insertion to ...
* name-lookup.c (get_method_slot): ... this new function.
(lookup_fnfields_slot_nolazy): Cope with NULL slot.
* name-lookup.h (get_method_slot): Declare.
* decl.c (cxx_init_decl_processinng): Give conv_op_marker a more
realistic type.
(grok_special_member_properties): Set
TYPE_HAS_CONVERSION. Expicitly look at DECL_NAME for specialness.
Improve TYPE_HAS_CONSTEXPR_CTOR setting.
* cp-tree.h (lang_decl_base): Rename template_conv_p to
unknown_bound_p.
(DECL_CONV_FN_P): Don't check NULL DECL_NAME.
......
......@@ -1011,57 +1011,12 @@ add_method (tree type, tree method, bool via_using)
if (method == error_mark_node)
return false;
vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (type);
if (!method_vec)
{
/* Make a new method vector. We start with 8 entries. */
vec_alloc (method_vec, 8);
CLASSTYPE_METHOD_VEC (type) = method_vec;
}
/* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */
grok_special_member_properties (method);
bool insert_p = true;
tree method_name = DECL_NAME (method);
bool complete_p = COMPLETE_TYPE_P (type);
bool conv_p = IDENTIFIER_CONV_OP_P (method_name);
if (conv_p)
method_name = conv_op_identifier;
/* See if we already have an entry with this name. */
unsigned slot;
tree m;
for (slot = 0; vec_safe_iterate (method_vec, slot, &m); ++slot)
{
m = DECL_NAME (OVL_FIRST (m));
if (m == method_name)
{
insert_p = false;
break;
}
if (complete_p && m > method_name)
break;
}
tree current_fns = insert_p ? NULL_TREE : (*method_vec)[slot];
tree *slot = get_method_slot (type, DECL_NAME (method));
tree current_fns = *slot;
tree conv_marker = NULL_TREE;
if (conv_p)
{
/* For conversion operators, we prepend a dummy overload
pointing at conv_op_marker. That function's DECL_NAME is
conv_op_identifier, so we can use identifier equality to
locate it. */
if (current_fns)
{
gcc_checking_assert (OVL_FUNCTION (current_fns) == conv_op_marker);
conv_marker = current_fns;
current_fns = OVL_CHAIN (current_fns);
}
else
conv_marker = ovl_make (conv_op_marker, NULL_TREE);
}
gcc_assert (!DECL_EXTERN_C_P (method));
/* Check to see if we've already got this method. */
......@@ -1209,36 +1164,11 @@ add_method (tree type, tree method, bool via_using)
current_fns = ovl_insert (method, current_fns, via_using);
if (conv_p)
{
TYPE_HAS_CONVERSION (type) = 1;
/* Prepend the marker function. */
OVL_CHAIN (conv_marker) = current_fns;
current_fns = conv_marker;
}
else if (!complete_p && !IDENTIFIER_CDTOR_P (DECL_NAME (method)))
if (!DECL_CONV_FN_P (method) && !COMPLETE_TYPE_P (type))
push_class_level_binding (DECL_NAME (method), current_fns);
if (insert_p)
{
bool reallocated;
*slot = current_fns;
/* We only expect to add few methods in the COMPLETE_P case, so
just make room for one more method in that case. */
if (complete_p)
reallocated = vec_safe_reserve_exact (method_vec, 1);
else
reallocated = vec_safe_reserve (method_vec, 1);
if (reallocated)
CLASSTYPE_METHOD_VEC (type) = method_vec;
if (slot == method_vec->length ())
method_vec->quick_push (current_fns);
else
method_vec->quick_insert (slot, current_fns);
}
else
/* Replace the current slot. */
(*method_vec)[slot] = current_fns;
return true;
}
......
......@@ -4073,13 +4073,6 @@ cxx_init_decl_processing (void)
noexcept_deferred_spec = build_tree_list (make_node (DEFERRED_NOEXCEPT),
NULL_TREE);
/* Create the conversion operator marker. This operator's DECL_NAME
is in the identifier table, so we can use identifier equality to
find it. This has no type and no context, so we can't
accidentally think it a real function. */
conv_op_marker = build_lang_decl (FUNCTION_DECL, conv_op_identifier,
NULL_TREE);
#if 0
record_builtin_type (RID_MAX, NULL, string_type_node);
#endif
......@@ -4094,6 +4087,12 @@ cxx_init_decl_processing (void)
void_ftype_ptr
= build_exception_variant (void_ftype_ptr, empty_except_spec);
/* Create the conversion operator marker. This operator's DECL_NAME
is in the identifier table, so we can use identifier equality to
find it. */
conv_op_marker = build_lang_decl (FUNCTION_DECL, conv_op_identifier,
void_ftype);
/* C++ extensions */
unknown_type_node = make_node (LANG_TYPE);
......@@ -12793,7 +12792,7 @@ grok_special_member_properties (tree decl)
return;
class_type = DECL_CONTEXT (decl);
if (DECL_CONSTRUCTOR_P (decl))
if (IDENTIFIER_CTOR_P (DECL_NAME (decl)))
{
int ctor = copy_fn_p (decl);
......@@ -12823,10 +12822,10 @@ grok_special_member_properties (tree decl)
TYPE_HAS_LIST_CTOR (class_type) = 1;
if (DECL_DECLARED_CONSTEXPR_P (decl)
&& !copy_fn_p (decl) && !move_fn_p (decl))
&& !ctor && !move_fn_p (decl))
TYPE_HAS_CONSTEXPR_CTOR (class_type) = 1;
}
else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
else if (DECL_NAME (decl) == cp_assignment_operator_id (NOP_EXPR))
{
/* [class.copy]
......@@ -12847,6 +12846,9 @@ grok_special_member_properties (tree decl)
else if (move_fn_p (decl) && user_provided_p (decl))
TYPE_HAS_COMPLEX_MOVE_ASSIGN (class_type) = 1;
}
else if (IDENTIFIER_CONV_OP_P (DECL_NAME (decl)))
TYPE_HAS_CONVERSION (class_type) = true;
/* Destructors are handled in check_methods. */
}
......
......@@ -1155,13 +1155,18 @@ lookup_fnfields_slot_nolazy (tree type, tree name)
}
else
for (int i = 0; vec_safe_iterate (method_vec, i, &fns); ++i)
{
if (OVL_NAME (fns) == lookup)
{
val = fns;
break;
}
}
/* 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
conversion operator was requested. */
......@@ -1312,6 +1317,74 @@ lookup_fnfields_slot (tree type, tree name)
return lookup_fnfields_slot_nolazy (type, name);
}
/* Find the slot containing overloads called 'NAME'. If there is no
such slot, create an empty one. KLASS might be complete at this
point, in which case we need to preserve ordering. Deals with
conv_op marker handling. */
tree *
get_method_slot (tree klass, tree name)
{
bool complete_p = COMPLETE_TYPE_P (klass);
vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (klass);
if (!method_vec)
{
vec_alloc (method_vec, 8);
CLASSTYPE_METHOD_VEC (klass) = method_vec;
}
if (IDENTIFIER_CONV_OP_P (name))
name = conv_op_identifier;
unsigned ix, length = method_vec->length ();
for (ix = 0; ix < length; ix++)
{
tree *slot = &(*method_vec)[ix];
tree fn_name = OVL_NAME (*slot);
if (fn_name == name)
{
if (name == conv_op_identifier)
{
gcc_checking_assert (OVL_FUNCTION (*slot) == conv_op_marker);
/* Skip the conv-op marker. */
slot = &OVL_CHAIN (*slot);
}
return slot;
}
if (complete_p && fn_name > name)
break;
}
/* No slot found. Create one at IX. We know in this case that our
caller will succeed in adding the function. */
if (complete_p)
{
/* Do exact allocation when complete, as we don't expect to add
many. */
vec_safe_reserve_exact (method_vec, 1);
method_vec->quick_insert (ix, NULL_TREE);
}
else
{
gcc_checking_assert (ix == length);
vec_safe_push (method_vec, NULL_TREE);
}
CLASSTYPE_METHOD_VEC (klass) = method_vec;
tree *slot = &(*method_vec)[ix];
if (name == conv_op_identifier)
{
/* Install the marker prefix. */
*slot = ovl_make (conv_op_marker, NULL_TREE);
slot = &OVL_CHAIN (*slot);
}
return slot;
}
static struct {
gt_pointer_operator new_value;
void *cookie;
......
......@@ -322,6 +322,7 @@ extern tree lookup_arg_dependent (tree, tree, vec<tree, va_gc> *);
extern tree lookup_field_1 (tree, tree, bool);
extern tree lookup_fnfields_slot (tree, tree);
extern tree lookup_fnfields_slot_nolazy (tree, tree);
extern tree *get_method_slot (tree klass, tree name);
extern void resort_type_method_vec (void *, void *,
gt_pointer_operator, void *);
extern void set_class_bindings (tree);
......
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