cp-tree.h (ovl_iterator::using_p): New predicate.
authorNathan Sidwell <nathan@acm.org>
Wed, 17 May 2017 12:37:30 +0000 (12:37 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Wed, 17 May 2017 12:37:30 +0000 (12:37 +0000)
* cp-tree.h (ovl_iterator::using_p): New predicate.
(ovl_iterator::remove_node): New worker.
(ovl_insert): Declare.
* tree.c (ovl_insert): New.
(ovl_iterator::remove_node): New.
* class.c (add_method): Use ovl_iterator, ovl_insert.
(clone_function_decl): Fix description.
(clone_constructors_and_destructors): Use ovl_iterator.

From-SVN: r248151

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/tree.c

index 923e2ea..7136b5d 100644 (file)
@@ -1,5 +1,14 @@
 2017-05-17  Nathan Sidwell  <nathan@acm.org>
 
+       * cp-tree.h (ovl_iterator::using_p): New predicate.
+       (ovl_iterator::remove_node): New worker.
+       (ovl_insert): Declare.
+       * tree.c (ovl_insert): New.
+       (ovl_iterator::remove_node): New.
+       * class.c (add_method): Use ovl_iterator, ovl_insert.
+       (clone_function_decl): Fix description.
+       (clone_constructors_and_destructors): Use ovl_iterator.
+
        * class.c (handle_using_decl): Use OVL_FIRST, ovl_iterator.
        (maybe_warn_about_overly_private_class): Use ovl_iterator.
        (method_name_cmp, resort_method_name_cmp): Use OVL_NAME.
index bda4c10..6f3f3e6 100644 (file)
@@ -1010,7 +1010,6 @@ bool
 add_method (tree type, tree method, bool via_using)
 {
   unsigned slot;
-  tree overload;
   bool template_conv_p = false;
   bool conv_p;
   vec<tree, va_gc> *method_vec;
@@ -1059,7 +1058,7 @@ add_method (tree type, tree method, bool via_using)
           vec_safe_iterate (method_vec, slot, &m);
           ++slot)
        {
-         m = OVL_CURRENT (m);
+         m = OVL_FIRST (m);
          if (template_conv_p)
            {
              if (TREE_CODE (m) == TEMPLATE_DECL
@@ -1083,24 +1082,23 @@ add_method (tree type, tree method, bool via_using)
   current_fns = insert_p ? NULL_TREE : (*method_vec)[slot];
 
   /* Check to see if we've already got this method.  */
-  for (tree *p = &current_fns; *p; )
+  for (ovl_iterator iter (current_fns); iter; ++iter)
     {
-      tree fns = *p;
-      tree fn = OVL_CURRENT (fns);
+      tree fn = *iter;
       tree fn_type;
       tree method_type;
       tree parms1;
       tree parms2;
 
       if (TREE_CODE (fn) != TREE_CODE (method))
-       goto cont;
+       continue;
 
       /* Two using-declarations can coexist, we'll complain about ambiguity in
         overload resolution.  */
-      if (via_using && TREE_CODE (fns) == OVERLOAD && OVL_USED (fns)
+      if (via_using && iter.using_p ()
          /* Except handle inherited constructors specially.  */
          && ! DECL_CONSTRUCTOR_P (fn))
-       goto cont;
+       continue;
 
       /* [over.load] Member function declarations with the
         same name and the same parameter types cannot be
@@ -1134,7 +1132,7 @@ add_method (tree type, tree method, bool via_using)
              == FUNCTION_REF_QUALIFIED (method_type))
          && (type_memfn_quals (fn_type) != type_memfn_quals (method_type)
              || type_memfn_rqual (fn_type) != type_memfn_rqual (method_type)))
-         goto cont;
+         continue;
 
       /* For templates, the return type and template parameters
         must be identical.  */
@@ -1143,7 +1141,7 @@ add_method (tree type, tree method, bool via_using)
                            TREE_TYPE (method_type))
              || !comp_template_parms (DECL_TEMPLATE_PARMS (fn),
                                       DECL_TEMPLATE_PARMS (method))))
-       goto cont;
+       continue;
 
       if (! DECL_STATIC_FUNCTION_P (fn))
        parms1 = TREE_CHAIN (parms1);
@@ -1187,8 +1185,9 @@ add_method (tree type, tree method, bool via_using)
                    mangle_decl (method);
                }
              cgraph_node::record_function_versions (fn, method);
-             goto cont;
+             continue;
            }
+
          if (DECL_INHERITED_CTOR (method))
            {
              if (DECL_INHERITED_CTOR (fn))
@@ -1202,7 +1201,7 @@ add_method (tree type, tree method, bool via_using)
                          /* Inheriting the same constructor along different
                             paths, combine them.  */
                          SET_DECL_INHERITED_CTOR
-                           (fn, ovl_cons (DECL_INHERITED_CTOR (method),
+                           (fn, ovl_make (DECL_INHERITED_CTOR (method),
                                           DECL_INHERITED_CTOR (fn)));
                          /* And discard the new one.  */
                          return false;
@@ -1210,7 +1209,7 @@ add_method (tree type, tree method, bool via_using)
                      else
                        /* Inherited ctors can coexist until overload
                           resolution.  */
-                       goto cont;
+                       continue;
                    }
                  error_at (DECL_SOURCE_LOCATION (method),
                            "%q#D", method);
@@ -1228,8 +1227,8 @@ add_method (tree type, tree method, bool via_using)
          else if (flag_new_inheriting_ctors
                   && DECL_INHERITED_CTOR (fn))
            {
-             /* Hide the inherited constructor.  */
-             *p = OVL_NEXT (fns);
+             /* Remove the inherited constructor.  */
+             current_fns = iter.remove_node (current_fns);
              continue;
            }
          else
@@ -1238,33 +1237,19 @@ add_method (tree type, tree method, bool via_using)
              error ("with %q+#D", fn);
              return false;
            }
-
        }
-
-    cont:
-      if (TREE_CODE (fns) == OVERLOAD)
-       p = &OVL_CHAIN (fns);
-      else
-       break;
     }
 
   /* A class should never have more than one destructor.  */
   if (current_fns && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
     return false;
 
-  /* Add the new binding.  */
-  if (via_using)
-    {
-      overload = ovl_cons (method, current_fns);
-      OVL_USED (overload) = true;
-    }
-  else
-    overload = build_overload (method, current_fns);
+  current_fns = ovl_insert (method, current_fns, via_using);
 
   if (conv_p)
     TYPE_HAS_CONVERSION (type) = 1;
   else if (slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
-    push_class_level_binding (DECL_NAME (method), overload);
+    push_class_level_binding (DECL_NAME (method), current_fns);
 
   if (insert_p)
     {
@@ -1279,13 +1264,13 @@ add_method (tree type, tree method, bool via_using)
       if (reallocated)
        CLASSTYPE_METHOD_VEC (type) = method_vec;
       if (slot == method_vec->length ())
-       method_vec->quick_push (overload);
+       method_vec->quick_push (current_fns);
       else
-       method_vec->quick_insert (slot, overload);
+       method_vec->quick_insert (slot, current_fns);
     }
   else
     /* Replace the current slot.  */
-    (*method_vec)[slot] = overload;
+    (*method_vec)[slot] = current_fns;
   return true;
 }
 
@@ -4873,8 +4858,7 @@ decl_cloned_function_p (const_tree decl, bool just_testing)
 
 /* Produce declarations for all appropriate clones of FN.  If
    UPDATE_METHODS is true, the clones are added to the
-   CLASTYPE_METHOD_VEC.  VIA_USING indicates whether these are cloning
-   decls brought in via using declarations (i.e. inheriting ctors).  */
+   CLASSTYPE_METHOD_VEC.  */
 
 void
 clone_function_decl (tree fn, bool update_methods)
@@ -5017,8 +5001,6 @@ adjust_clone_args (tree decl)
 static void
 clone_constructors_and_destructors (tree t)
 {
-  tree fns;
-
   /* If for some reason we don't have a CLASSTYPE_METHOD_VEC, we bail
      out now.  */
   if (!CLASSTYPE_METHOD_VEC (t))
@@ -5026,10 +5008,10 @@ clone_constructors_and_destructors (tree t)
 
   /* While constructors can be via a using declaration, at this point
      we no longer need to know that.  */
-  for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
-    clone_function_decl (OVL_CURRENT (fns), /*update_methods=*/true);
-  for (fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
-    clone_function_decl (OVL_CURRENT (fns), /*update_methods=*/true);
+  for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
+    clone_function_decl (*iter, /*update_methods=*/true);
+  for (ovl_iterator iter (CLASSTYPE_DESTRUCTORS (t)); iter; ++iter)
+    clone_function_decl (*iter, /*update_methods=*/true);
 }
 
 /* Deduce noexcept for a destructor DTOR.  */
index 0efc5db..942ac61 100644 (file)
@@ -680,6 +680,22 @@ class ovl_iterator
 
     return fn;
   }
+
+ public:
+  /* Whether this overload was introduced by a using decl.  */
+  bool using_p () const
+  {
+    return TREE_CODE (ovl) == OVERLOAD && OVL_USED (ovl);
+  }
+  tree remove_node (tree head)
+  {
+    return remove_node (head, ovl);
+  }
+
+ private:
+  /* We make this a static function to avoid the address of the
+     iterator escaping the local context.  */
+  static tree remove_node (tree head, tree node);
 };
 
 /* Iterator over a (potentially) 2 dimensional overload, which is
@@ -6768,6 +6784,8 @@ extern tree build_ref_qualified_type              (tree, cp_ref_qualifier);
 inline tree ovl_first                          (tree) ATTRIBUTE_PURE;
 extern tree ovl_make                           (tree fn,
                                                 tree next = NULL_TREE);
+extern tree ovl_insert                         (tree fn, tree maybe_ovl,
+                                                bool using_p = false);
 extern tree lookup_add                         (tree lookup, tree ovl);
 extern int is_overloaded_fn                    (tree);
 extern tree dependent_name                     (tree);
index edc0120..7ea6ce2 100644 (file)
@@ -2124,6 +2124,65 @@ ovl_make (tree fn, tree next)
   return result;
 }
 
+/* Add FN to the (potentially NULL) overload set OVL.  USING_P is
+   true, if FN is via a using declaration.  Overloads are ordered as
+   using, regular.  */
+
+tree
+ovl_insert (tree fn, tree maybe_ovl, bool using_p)
+{
+  int weight = using_p;
+
+  tree result = NULL_TREE;
+  tree insert_after = NULL_TREE;
+
+  /* Find insertion point.  */
+  while (maybe_ovl && TREE_CODE (maybe_ovl) == OVERLOAD
+        && (weight < OVL_USED (maybe_ovl)))
+    {
+      if (!result)
+       result = maybe_ovl;
+      insert_after = maybe_ovl;
+      maybe_ovl = OVL_CHAIN (maybe_ovl);
+    }
+
+  tree trail = fn;
+  if (maybe_ovl || using_p || TREE_CODE (fn) == TEMPLATE_DECL)
+    {
+      trail = ovl_make (fn, maybe_ovl);
+      if (using_p)
+       OVL_USED (trail) = true;
+    }
+
+  if (insert_after)
+    {
+      TREE_CHAIN (insert_after) = trail;
+      TREE_TYPE (insert_after) = unknown_type_node;
+    }
+  else
+    result = trail;
+
+  return result;
+}
+
+/* NODE is on the overloads of OVL.  Remove it.  */
+
+tree
+ovl_iterator::remove_node (tree overload, tree node)
+{
+  tree *slot = &overload;
+  while (*slot != node)
+    slot = &OVL_CHAIN (*slot);
+
+  /* Stitch out NODE.  We don't have to worry about now making a
+     singleton overload (and consequently maybe setting its type),
+     because all uses of this function will be followed by inserting a
+     new node that must follow the place we've cut this out from.  */
+  *slot = OVL_CHAIN (node);
+
+  return overload;
+}
+
 /* Add a potential overload into a lookup set.  */
 
 tree