+2018-02-27 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/84426
+ * name-lookup.h (get_member_slot): Rename ...
+ (find_member_slot): ... here.
+ (add_member_slot): New.
+ * name-lookup.c (member_vec_linear_search): No need to check for
+ NULL slot.
+ (get_member_slot): Rename ...
+ (find_member_slot): ... here. Don't add slot for incomplete class.
+ (add_member_slot): New.
+ * class.c (add_method): Adjust get_member_slot rename. Bail out
+ if push_class_level_binding fails. Create slot and grok
+ properties once we're committed to insertion.
+
2018-02-27 Jason Merrill <jason@redhat.com>
PR c++/84489 - dependent default template argument
if (method == error_mark_node)
return false;
- /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */
- grok_special_member_properties (method);
-
- tree *slot = get_member_slot (type, DECL_NAME (method));
- tree current_fns = *slot;
-
gcc_assert (!DECL_EXTERN_C_P (method));
+ tree *slot = find_member_slot (type, DECL_NAME (method));
+ tree current_fns = slot ? *slot : NULL_TREE;
+
/* Check to see if we've already got this method. */
for (ovl_iterator iter (current_fns); iter; ++iter)
{
current_fns = ovl_insert (method, current_fns, via_using);
- if (!DECL_CONV_FN_P (method) && !COMPLETE_TYPE_P (type))
- push_class_level_binding (DECL_NAME (method), current_fns);
+ if (!COMPLETE_TYPE_P (type) && !DECL_CONV_FN_P (method)
+ && !push_class_level_binding (DECL_NAME (method), current_fns))
+ return false;
+
+ if (!slot)
+ slot = add_member_slot (type, DECL_NAME (method));
+
+ /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */
+ grok_special_member_properties (method);
*slot = current_fns;
member_vec_linear_search (vec<tree, va_gc> *member_vec, tree name)
{
for (int ix = member_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 = (*member_vec)[ix])
- {
- if (OVL_NAME (binding) == name)
- return binding;
- }
- else
- break;
+ if (OVL_NAME (binding) == name)
+ return binding;
return NULL_TREE;
}
}
/* 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. */
+ such slot and the class is complete, create an empty one, at the
+ correct point in the sorted member vector. Otherwise return NULL.
+ Deals with conv_op marker handling. */
tree *
-get_member_slot (tree klass, tree name)
+find_member_slot (tree klass, tree name)
{
bool complete_p = COMPLETE_TYPE_P (klass);
-
+
vec<tree, va_gc> *member_vec = CLASSTYPE_MEMBER_VEC (klass);
if (!member_vec)
{
break;
}
- /* No slot found. Create one at IX. We know in this case that our
- caller will succeed in adding the function. */
+ /* No slot found, add one if the class is complete. */
if (complete_p)
{
- /* Do exact allocation when complete, as we don't expect to add
- many. */
+ /* Do exact allocation, as we don't expect to add many. */
+ gcc_assert (name != conv_op_identifier);
vec_safe_reserve_exact (member_vec, 1);
+ CLASSTYPE_MEMBER_VEC (klass) = member_vec;
member_vec->quick_insert (ix, NULL_TREE);
+ return &(*member_vec)[ix];
}
- else
- {
- gcc_checking_assert (ix == length);
- vec_safe_push (member_vec, NULL_TREE);
- }
+
+ return NULL;
+}
+
+/* KLASS is an incomplete class to which we're adding a method NAME.
+ Add a slot and deal with conv_op marker handling. */
+
+tree *
+add_member_slot (tree klass, tree name)
+{
+ gcc_assert (!COMPLETE_TYPE_P (klass));
+
+ vec<tree, va_gc> *member_vec = CLASSTYPE_MEMBER_VEC (klass);
+ vec_safe_push (member_vec, NULL_TREE);
CLASSTYPE_MEMBER_VEC (klass) = member_vec;
- tree *slot = &(*member_vec)[ix];
- if (name == conv_op_identifier)
+ tree *slot = &member_vec->last ();
+ if (IDENTIFIER_CONV_OP_P (name))
{
/* Install the marker prefix. */
*slot = ovl_make (conv_op_marker, NULL_TREE);
extern tree search_anon_aggr (tree, tree);
extern tree get_class_binding_direct (tree, tree, int type_or_fns = -1);
extern tree get_class_binding (tree, tree, int type_or_fns = -1);
-extern tree *get_member_slot (tree klass, tree name);
+extern tree *find_member_slot (tree klass, tree name);
+extern tree *add_member_slot (tree klass, tree name);
extern void resort_type_member_vec (void *, void *,
gt_pointer_operator, void *);
extern void set_class_bindings (tree, unsigned extra = 0);