tree-iterator: C++11 range-for and tree_stmt_iterator
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.
This commit is contained in:
parent
f7a07f5a5d
commit
0f54cc9c63
6 changed files with 55 additions and 48 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue