From: Nathan Sidwell Date: Tue, 27 Feb 2018 20:52:15 +0000 (+0000) Subject: [PR c++/84426] ICE after conflicting member decl X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=10b5c9829b7e162342e8e730b6ed072bcd0dc7b2;p=gcc.git [PR c++/84426] ICE after conflicting member decl https://gcc.gnu.org/ml/gcc-patches/2018-02/msg01529.html 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. PR c++/84426 * g++.dg/lookup/pr84426.C: New. From-SVN: r258042 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b2973d1b301..dbb678cbd48 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2018-02-27 Nathan Sidwell + + 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 PR c++/84489 - dependent default template argument diff --git a/gcc/cp/class.c b/gcc/cp/class.c index afa5c41bfff..8348552a05b 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -993,14 +993,11 @@ add_method (tree type, tree method, bool via_using) 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) { @@ -1146,8 +1143,15 @@ add_method (tree type, tree method, bool via_using) 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; diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 0f00328e96e..c61f01c4f88 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -1146,17 +1146,9 @@ static tree member_vec_linear_search (vec *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; } @@ -1334,15 +1326,15 @@ get_class_binding (tree klass, tree name, int type_or_fns) } /* 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 *member_vec = CLASSTYPE_MEMBER_VEC (klass); if (!member_vec) { @@ -1389,24 +1381,34 @@ get_member_slot (tree klass, tree name) 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 *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); diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index e78d4b7cef5..fe15136b227 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -310,7 +310,8 @@ extern tree lookup_arg_dependent (tree, tree, vec *); 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5431093d456..eaf0d6a21b7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-02-27 Nathan Sidwell + + PR c++/84426 + * g++.dg/lookup/pr84426.C: New. + 2018-02-27 Richard Biener PR tree-optimization/84512 diff --git a/gcc/testsuite/g++.dg/lookup/pr84426.C b/gcc/testsuite/g++.dg/lookup/pr84426.C new file mode 100644 index 00000000000..50ac11be73e --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/pr84426.C @@ -0,0 +1,9 @@ +// PR c++/84426 ICE after error + +struct A +{ + int foo; // { dg-message "previous" } + virtual void foo(); // { dg-error "conflict" } +}; + +struct B : A {}; // ICED here