]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-iterator: C++11 range-for and tree_stmt_iterator
authorJason Merrill <jason@redhat.com>
Sat, 3 Apr 2021 02:20:43 +0000 (22:20 -0400)
committerJason Merrill <jason@redhat.com>
Fri, 28 May 2021 13:33:11 +0000 (09:33 -0400)
Like my recent patch to add ovl_range and lkp_range in the C++ front end,
this patch adds the tsi_range adaptor for using C++11 range-based 'for' with
a STATEMENT_LIST, e.g.

  for (tree stmt : tsi_range (stmt_list)) { ... }

This also involves adding some operators to tree_stmt_iterator that are
needed for range-for iterators, and should also be useful in code that uses
the iterators directly.

The patch updates the suitable loops in the C++ front end, but does not
touch any loops elsewhere in the compiler.

gcc/ChangeLog:

* tree-iterator.h (struct tree_stmt_iterator): Add operator++,
operator--, operator*, operator==, and operator!=.
(class tsi_range): New.

gcc/cp/ChangeLog:

* constexpr.c (build_data_member_initialization): Use tsi_range.
(build_constexpr_constructor_member_initializers): Likewise.
(constexpr_fn_retval, cxx_eval_statement_list): Likewise.
(potential_constant_expression_1): Likewise.
* coroutines.cc (await_statement_expander): Likewise.
(await_statement_walker): Likewise.
* module.cc (trees_out::core_vals): Likewise.
* pt.c (tsubst_expr): Likewise.
* semantics.c (set_cleanup_locs): Likewise.

gcc/cp/constexpr.c
gcc/cp/coroutines.cc
gcc/cp/module.cc
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/tree-iterator.h

index 9cb761d7cd3a5a094e058af81646e6e0f5ba3515..297f2072de80dd50c7b1dd3dd2389c4992808d05 100644 (file)
@@ -330,12 +330,9 @@ build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec)
     return false;
   if (TREE_CODE (t) == STATEMENT_LIST)
     {
-      tree_stmt_iterator i;
-      for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
-       {
-         if (! build_data_member_initialization (tsi_stmt (i), vec))
-           return false;
-       }
+      for (tree stmt : tsi_range (t))
+       if (! build_data_member_initialization (stmt, vec))
+         return false;
       return true;
     }
   if (TREE_CODE (t) == CLEANUP_STMT)
@@ -577,10 +574,9 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
        break;
 
       case STATEMENT_LIST:
-       for (tree_stmt_iterator i = tsi_start (body);
-            !tsi_end_p (i); tsi_next (&i))
+       for (tree stmt : tsi_range (body))
          {
-           body = tsi_stmt (i);
+           body = stmt;
            if (TREE_CODE (body) == BIND_EXPR)
              break;
          }
@@ -617,10 +613,9 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
     }
   else if (TREE_CODE (body) == STATEMENT_LIST)
     {
-      tree_stmt_iterator i;
-      for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
+      for (tree stmt : tsi_range (body))
        {
-         ok = build_data_member_initialization (tsi_stmt (i), &vec);
+         ok = build_data_member_initialization (stmt, &vec);
          if (!ok)
            break;
        }
@@ -675,11 +670,10 @@ constexpr_fn_retval (tree body)
     {
     case STATEMENT_LIST:
       {
-       tree_stmt_iterator i;
        tree expr = NULL_TREE;
-       for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
+       for (tree stmt : tsi_range (body))
          {
-           tree s = constexpr_fn_retval (tsi_stmt (i));
+           tree s = constexpr_fn_retval (stmt);
            if (s == error_mark_node)
              return error_mark_node;
            else if (s == NULL_TREE)
@@ -5772,7 +5766,6 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t,
                         bool *non_constant_p, bool *overflow_p,
                         tree *jump_target)
 {
-  tree_stmt_iterator i;
   tree local_target;
   /* In a statement-expression we want to return the last value.
      For empty statement expression return void_node.  */
@@ -5782,9 +5775,8 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t,
       local_target = NULL_TREE;
       jump_target = &local_target;
     }
-  for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+  for (tree stmt : tsi_range (t))
     {
-      tree stmt = tsi_stmt (i);
       /* We've found a continue, so skip everything until we reach
         the label its jumping to.  */
       if (continues (jump_target))
@@ -8282,16 +8274,10 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
       }
 
     case STATEMENT_LIST:
-      {
-       tree_stmt_iterator i;
-       for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
-         {
-           if (!RECUR (tsi_stmt (i), any))
-             return false;
-         }
-       return true;
-      }
-      break;
+      for (tree stmt : tsi_range (t))
+       if (!RECUR (stmt, any))
+         return false;
+      return true;
 
     case MODIFY_EXPR:
       if (cxx_dialect < cxx14)
index 71662061f5a9f6b70408106dc2301cb58bf63d50..1bf1931e7be126584de024a7940dc5b2b73d16e8 100644 (file)
@@ -1764,10 +1764,9 @@ await_statement_expander (tree *stmt, int *do_subtree, void *d)
     return NULL_TREE; /* Just process the sub-trees.  */
   else if (TREE_CODE (*stmt) == STATEMENT_LIST)
     {
-      tree_stmt_iterator i;
-      for (i = tsi_start (*stmt); !tsi_end_p (i); tsi_next (&i))
+      for (tree &s : tsi_range (*stmt))
        {
-         res = cp_walk_tree (tsi_stmt_ptr (i), await_statement_expander,
+         res = cp_walk_tree (&s, await_statement_expander,
                              d, NULL);
          if (res)
            return res;
@@ -3509,10 +3508,9 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
     }
   else if (TREE_CODE (*stmt) == STATEMENT_LIST)
     {
-      tree_stmt_iterator i;
-      for (i = tsi_start (*stmt); !tsi_end_p (i); tsi_next (&i))
+      for (tree &s : tsi_range (*stmt))
        {
-         res = cp_walk_tree (tsi_stmt_ptr (i), await_statement_walker,
+         res = cp_walk_tree (&s, await_statement_walker,
                              d, NULL);
          if (res)
            return res;
index 02c19f55548129fe1e898bc9e8b4446a9c061361..f0fb014470688b0fa97d27e0ecbc5de86be6a2f7 100644 (file)
@@ -6094,9 +6094,8 @@ trees_out::core_vals (tree t)
       break;
 
     case STATEMENT_LIST:
-      for (tree_stmt_iterator iter = tsi_start (t);
-          !tsi_end_p (iter); tsi_next (&iter))
-       if (tree stmt = tsi_stmt (iter))
+      for (tree stmt : tsi_range (t))
+       if (stmt)
          WT (stmt);
       WT (NULL_TREE);
       break;
index bb22d685617e2bc61b64ca2d35cf76afafc0dcd0..b476ca8948de8f0378f4fc9f15ade3614fbb3923 100644 (file)
@@ -18152,9 +18152,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
     {
     case STATEMENT_LIST:
       {
-       tree_stmt_iterator i;
-       for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
-         RECUR (tsi_stmt (i));
+       for (tree stmt : tsi_range (t))
+         RECUR (stmt);
        break;
       }
 
index fe370a21366e4db86da39d516228318dba4bafd9..e40462d192a071033169f66fb64515dd87f9c64b 100644 (file)
@@ -613,9 +613,8 @@ set_cleanup_locs (tree stmts, location_t loc)
       set_cleanup_locs (CLEANUP_BODY (stmts), loc);
     }
   else if (TREE_CODE (stmts) == STATEMENT_LIST)
-    for (tree_stmt_iterator i = tsi_start (stmts);
-        !tsi_end_p (i); tsi_next (&i))
-      set_cleanup_locs (tsi_stmt (i), loc);
+    for (tree stmt : tsi_range (stmts))
+      set_cleanup_locs (stmt, loc);
 }
 
 /* Finish a scope.  */
index 076fff8644c4b494a7786003999d8a511c91e56a..a72d0d37f1cc0ad28cf2c4b932113634ca6cb144 100644 (file)
@@ -1,4 +1,4 @@
-/* Iterator routines for manipulating GENERIC tree statement list.
+/* Iterator routines for manipulating GENERIC tree statement list. -*- C++ -*-
    Copyright (C) 2003-2021 Free Software Foundation, Inc.
    Contributed by Andrew MacLeod  <amacleod@redhat.com>
 
@@ -32,6 +32,21 @@ along with GCC; see the file COPYING3.  If not see
 struct tree_stmt_iterator {
   struct tree_statement_list_node *ptr;
   tree container;
+
+  /* No need for user-defined constructors, the implicit definitions (or
+     aggregate initialization) are fine.  */
+
+  bool operator== (tree_stmt_iterator b) const
+    { return b.ptr == ptr && b.container == container; }
+  bool operator!= (tree_stmt_iterator b) const { return !(*this == b); }
+  tree_stmt_iterator &operator++ () { ptr = ptr->next; return *this; }
+  tree_stmt_iterator &operator-- () { ptr = ptr->prev; return *this; }
+  tree_stmt_iterator operator++ (int)
+    { tree_stmt_iterator x = *this; ++*this; return x; }
+  tree_stmt_iterator operator-- (int)
+    { tree_stmt_iterator x = *this; --*this; return x; }
+  tree &operator* () { return ptr->stmt; }
+  tree operator* () const { return ptr->stmt; }
 };
 
 static inline tree_stmt_iterator
@@ -71,27 +86,38 @@ tsi_one_before_end_p (tree_stmt_iterator i)
 static inline void
 tsi_next (tree_stmt_iterator *i)
 {
-  i->ptr = i->ptr->next;
+  ++(*i);
 }
 
 static inline void
 tsi_prev (tree_stmt_iterator *i)
 {
-  i->ptr = i->ptr->prev;
+  --(*i);
 }
 
 static inline tree *
 tsi_stmt_ptr (tree_stmt_iterator i)
 {
-  return &i.ptr->stmt;
+  return &(*i);
 }
 
 static inline tree
 tsi_stmt (tree_stmt_iterator i)
 {
-  return i.ptr->stmt;
+  return *i;
 }
 
+/* Make tree_stmt_iterator work as a C++ range, e.g.
+   for (tree stmt : tsi_range (stmt_list)) { ... }  */
+class tsi_range
+{
+  tree t;
+ public:
+  tsi_range (tree t): t(t) { }
+  tree_stmt_iterator begin() const { return tsi_start (t); }
+  tree_stmt_iterator end() const { return { nullptr, t }; }
+};
+
 enum tsi_iterator_update
 {
   TSI_NEW_STMT,                /* Only valid when single statement is added, move