From 0f54cc9c63842ddfa921530cb499743cafc9b177 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 2 Apr 2021 22:20:43 -0400 Subject: 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. --- gcc/tree-iterator.h | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'gcc/tree-iterator.h') diff --git a/gcc/tree-iterator.h b/gcc/tree-iterator.h index 076fff8..a72d0d3 100644 --- a/gcc/tree-iterator.h +++ b/gcc/tree-iterator.h @@ -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 @@ -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 -- cgit v1.1