[pushed] c++: C++11 range-for and ovl/lkp_iterator

Message ID 20210501162748.3164755-1-jason@redhat.com
State New
Headers show
Series
  • [pushed] c++: C++11 range-for and ovl/lkp_iterator
Related show

Commit Message

Andrew MacLeod via Gcc-patches May 1, 2021, 4:27 p.m.
We can't use C++11 range-based 'for' over a tree directly, because we don't
know what kind of range we want to use it as.  I suppose in some cases we
could guess, but it seems better to tersely make it explicit.  This patch
adds range adaptors ovl_range and lkp_range for use as the range of a
range-for, e.g.

  for (tree fn : lkp_range (fns)) { ... }

This patch also removes the private copy ops from ovl_iterator; it's
necessary for range-for, and these are effectively C++ forward_iterators,
which allow copying, so I don't see a reason to prevent it.  A bit more
would need to be done to make them actually conform as C++11 forward
iterators, but I don't think we particularly want to #include <iterator>
yet.

Tested x86_64-pc-linux-gnu, applying to trunk.

gcc/cp/ChangeLog:

	* cp-tree.h (class ovl_iterator): Allow copying.  Add op==.
	(class ovl_range, class lkp_range): New.
	* call.c (build_op_call_1, add_candidates): Use them.
	(build_op_delete_call, has_trivial_copy_assign_p): Likewise.
	(has_trivial_copy_p): Likewise.
	* class.c (handle_using_decl, get_basefndecls): Likewise.
	(maybe_warn_about_overly_private_class): Likewise.
	(warn_hidden, add_implicitly_declared_members): Likewise.
	(check_methods, clone_constructors_and_destructors): Likewise.
	(type_has_user_nondefault_constructor): Likewise.
---
 gcc/cp/cp-tree.h | 34 +++++++++++++++++++++++++++++-----
 gcc/cp/call.c    | 23 ++++++-----------------
 gcc/cp/class.c   | 45 ++++++++++++++++++++-------------------------
 3 files changed, 55 insertions(+), 47 deletions(-)


base-commit: 3c65858787dc52b65b26fa7018587c01510f442c
-- 
2.27.0

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 368d9f5adf7..a08867aea62 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -817,11 +817,6 @@  class ovl_iterator {
   {
   }
 
- private:
-  /* Do not duplicate.  */
-  ovl_iterator &operator= (const ovl_iterator &);
-  ovl_iterator (const ovl_iterator &);
-
  public:
   operator bool () const
   {
@@ -841,6 +836,10 @@  class ovl_iterator {
 
     return fn;
   }
+  bool operator== (const ovl_iterator &o) const
+  {
+    return ovl == o.ovl;
+  }
   tree get_using () const
   {
     gcc_checking_assert (using_p ());
@@ -903,6 +902,19 @@  class ovl_iterator {
   static tree reveal_node (tree ovl, tree node);
 };
 
+/* Treat a tree as a range of ovl_iterator, e.g.
+   for (tree f : ovl_range (fns)) { ... }  */
+
+class ovl_range
+{
+  tree t;
+  bool allow;
+public:
+  explicit ovl_range (tree t, bool allow = false): t(t), allow(allow) { }
+  ovl_iterator begin() { return ovl_iterator (t, allow); }
+  ovl_iterator end() { return ovl_iterator (NULL_TREE, allow); }
+};
+
 /* Iterator over a (potentially) 2 dimensional overload, which is
    produced by name lookup.  */
 
@@ -935,6 +947,18 @@  class lkp_iterator : public ovl_iterator {
   }
 };
 
+/* Treat a tree as a range of lkp_iterator, e.g.
+   for (tree f : lkp_range (fns)) { ... }  */
+
+class lkp_range
+{
+  tree t;
+public:
+  lkp_range (tree t): t(t) { }
+  lkp_iterator begin() { return lkp_iterator (t); }
+  lkp_iterator end() { return lkp_iterator (NULL_TREE); }
+};
+
 /* hash traits for declarations.  Hashes potential overload sets via
    DECL_NAME.  */
 
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 678e120a165..57bac05fe70 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4914,10 +4914,8 @@  build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain)
 	  || TYPE_REFFN_P (totype)
 	  || (TYPE_REF_P (totype)
 	      && TYPE_PTRFN_P (TREE_TYPE (totype))))
-	for (ovl_iterator iter (TREE_VALUE (convs)); iter; ++iter)
+	for (tree fn : ovl_range (TREE_VALUE (convs)))
 	  {
-	    tree fn = *iter;
-
 	    if (DECL_NONCONVERTING_P (fn))
 	      continue;
 
@@ -5981,10 +5979,8 @@  add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,
     which = non_templates;
 
  again:
-  for (lkp_iterator iter (fns); iter; ++iter)
+  for (tree fn : lkp_range (fns))
     {
-      fn = *iter;
-
       if (check_converting && DECL_NONCONVERTING_P (fn))
 	continue;
       if (check_list_ctor && !is_list_ctor (fn))
@@ -7016,10 +7012,8 @@  build_op_delete_call (enum tree_code code, tree addr, tree size,
 	     the usual deallocation function, so we shouldn't complain
 	     about using the operator delete (void *, size_t).  */
 	  if (DECL_CLASS_SCOPE_P (fn))
-	    for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (fns));
-		 iter; ++iter)
+	    for (tree elt : lkp_range (MAYBE_BASELINK_FUNCTIONS (fns)))
 	      {
-		tree elt = *iter;
 		if (usual_deallocation_fn_p (elt)
 		    && FUNCTION_ARG_CHAIN (elt) == void_list_node)
 		  goto ok;
@@ -7062,9 +7056,8 @@  build_op_delete_call (enum tree_code code, tree addr, tree size,
        allocation function. If the lookup finds a single matching
        deallocation function, that function will be called; otherwise, no
        deallocation function will be called."  */
-    for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (fns)); iter; ++iter)
+    for (tree elt : lkp_range (MAYBE_BASELINK_FUNCTIONS (fns)))
       {
-	tree elt = *iter;
 	dealloc_info di_elt;
 	if (usual_deallocation_fn_p (elt, &di_elt))
 	  {
@@ -9669,10 +9662,8 @@  has_trivial_copy_assign_p (tree type, bool access, bool *hasassign)
   /* Iterate over overloads of the assignment operator, checking
      accessible copy assignments for triviality.  */
 
-  for (ovl_iterator oi (fns); oi; ++oi)
+  for (tree f : ovl_range (fns))
     {
-      tree f = *oi;
-
       /* Skip operators that aren't copy assignments.  */
       if (!copy_fn_p (f))
 	continue;
@@ -9715,10 +9706,8 @@  has_trivial_copy_p (tree type, bool access, bool hasctor[2])
   tree fns = get_class_binding (type, complete_ctor_identifier);
   bool all_trivial = true;
 
-  for (ovl_iterator oi (fns); oi; ++oi)
+  for (tree f : ovl_range (fns))
     {
-      tree f = *oi;
-
       /* Skip template constructors.  */
       if (TREE_CODE (f) != FUNCTION_DECL)
 	continue;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index dad3849d44f..66bc1eea682 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1347,10 +1347,10 @@  handle_using_decl (tree using_decl, tree t)
 
   /* Make type T see field decl FDECL with access ACCESS.  */
   if (flist)
-    for (ovl_iterator iter (flist); iter; ++iter)
+    for (tree f : ovl_range (flist))
       {
-	add_method (t, *iter, true);
-	alter_access (t, *iter, access);
+	add_method (t, f, true);
+	alter_access (t, f, access);
       }
   else if (USING_DECL_UNRELATED_P (using_decl))
     {
@@ -2259,18 +2259,20 @@  maybe_warn_about_overly_private_class (tree t)
       if (!TYPE_HAS_COPY_CTOR (t))
 	nonprivate_ctor = true;
       else
-	for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t));
-	     !nonprivate_ctor && iter; ++iter)
-	  if (TREE_PRIVATE (*iter))
+	for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (t)))
+	  if (TREE_PRIVATE (fn))
 	    continue;
-	  else if (copy_fn_p (*iter) || move_fn_p (*iter))
+	  else if (copy_fn_p (fn) || move_fn_p (fn))
 	    /* Ideally, we wouldn't count any constructor that takes
 	       an argument of the class type as a parameter, because
 	       such things cannot be used to construct an instance of
 	       the class unless you already have one.  */
-	    copy_or_move = *iter;
+	    copy_or_move = fn;
 	  else
-	    nonprivate_ctor = true;
+	    {
+	      nonprivate_ctor = true;
+	      break;
+	    }
 
       if (!nonprivate_ctor)
 	{
@@ -2876,10 +2878,8 @@  get_basefndecls (tree name, tree t, vec<tree> *base_fndecls)
   bool found_decls = false;
 
   /* Find virtual functions in T with the indicated NAME.  */
-  for (ovl_iterator iter (get_class_binding (t, name)); iter; ++iter)
+  for (tree method : ovl_range (get_class_binding (t, name)))
     {
-      tree method = *iter;
-
       if (TREE_CODE (method) == FUNCTION_DECL && DECL_VINDEX (method))
 	{
 	  base_fndecls->safe_push (method);
@@ -2988,9 +2988,8 @@  warn_hidden (tree t)
 	  continue;
 
 	/* Remove any overridden functions.  */
-	for (ovl_iterator iter (fns); iter; ++iter)
+	for (tree fndecl : ovl_range (fns))
 	  {
-	    tree fndecl = *iter;
 	    if (TREE_CODE (fndecl) == FUNCTION_DECL
 		&& DECL_VINDEX (fndecl))
 	      {
@@ -3334,8 +3333,8 @@  add_implicitly_declared_members (tree t, tree* access_decls,
 	  tree ctor_list = decl;
 	  location_t loc = input_location;
 	  input_location = DECL_SOURCE_LOCATION (using_decl);
-	  for (ovl_iterator iter (ctor_list); iter; ++iter)
-	    one_inherited_ctor (*iter, t, using_decl);
+	  for (tree fn : ovl_range (ctor_list))
+	    one_inherited_ctor (fn, t, using_decl);
 	  *access_decls = TREE_CHAIN (*access_decls);
 	  input_location = loc;
 	}
@@ -4751,9 +4750,8 @@  check_methods (tree t)
 	TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = true;
     }
 
-  for (ovl_iterator i (CLASSTYPE_CONSTRUCTORS (t)); i; ++i)
+  for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (t)))
     {
-      tree fn = *i;
       if (!user_provided_p (fn))
 	/* Might be trivial.  */;
       else if (copy_fn_p (fn))
@@ -4762,10 +4760,8 @@  check_methods (tree t)
 	TYPE_HAS_COMPLEX_MOVE_CTOR (t) = true;
     }
 
-  for (ovl_iterator i (get_class_binding_direct (t, assign_op_identifier));
-       i; ++i)
+  for (tree fn : ovl_range (get_class_binding_direct (t, assign_op_identifier)))
     {
-      tree fn = *i;
       if (!user_provided_p (fn))
 	/* Might be trivial.  */;
       else if (copy_fn_p (fn))
@@ -5107,8 +5103,8 @@  clone_constructors_and_destructors (tree t)
 {
   /* We do not need to propagate the usingness to the clone, at this
      point that is not needed.  */
-  for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
-    clone_cdtor (*iter, /*update_methods=*/true);
+  for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (t)))
+    clone_cdtor (fn, /*update_methods=*/true);
 
   if (tree dtor = CLASSTYPE_DESTRUCTOR (t))
     clone_cdtor (dtor, /*update_methods=*/true);
@@ -5283,9 +5279,8 @@  type_has_user_nondefault_constructor (tree t)
   if (!TYPE_HAS_USER_CONSTRUCTOR (t))
     return false;
 
-  for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
+  for (tree fn : ovl_range (CLASSTYPE_CONSTRUCTORS (t)))
     {
-      tree fn = *iter;
       if (user_provided_p (fn)
 	  && (TREE_CODE (fn) == TEMPLATE_DECL
 	      || (skip_artificial_parms_for (fn, DECL_ARGUMENTS (fn))