[PR c++/84426] ICE after conflicting member decl
authorNathan Sidwell <nathan@acm.org>
Tue, 27 Feb 2018 20:52:15 +0000 (20:52 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 27 Feb 2018 20:52:15 +0000 (20:52 +0000)
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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/pr84426.C [new file with mode: 0644]

index b2973d1b301779248b5bf37e4254e1d1a3da2da4..dbb678cbd48c795d7d5f5d197de4a24d25111553 100644 (file)
@@ -1,3 +1,18 @@
+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
index afa5c41bfff0e10b3c4b8f29475cd2bcdb56627f..8348552a05b613762b2f385cf608d2372c8ac96c 100644 (file)
@@ -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;
 
index 0f00328e96e310aacbc634de81e403eb9cca8134..c61f01c4f88bec01d41b901021ff0223ad257434 100644 (file)
@@ -1146,17 +1146,9 @@ static tree
 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;
 }
@@ -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<tree, va_gc> *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<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);
index e78d4b7cef5056b52738fc9d04f5499ed7012b8d..fe15136b227fc84b92a6c51cd4e8fe3185046be4 100644 (file)
@@ -310,7 +310,8 @@ extern tree lookup_arg_dependent (tree, tree, vec<tree, va_gc> *);
 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);
index 5431093d456edb407f3fbb6af29bd0dabf428a4e..eaf0d6a21b767759ebc6b3aee2bba6d122f61650 100644 (file)
@@ -1,3 +1,8 @@
+2018-02-27  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/84426
+       * g++.dg/lookup/pr84426.C: New.
+
 2018-02-27  Richard Biener  <rguenther@suse.de>
 
        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 (file)
index 0000000..50ac11b
--- /dev/null
@@ -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