From 3307b9a07a3c515c6805d435e4bedada77687183 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 2 Mar 2021 16:30:41 -0500 Subject: c++: C++11 range-for and ovl/lkp_iterator 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 yet. 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/call.c | 23 ++++++----------------- gcc/cp/class.c | 45 ++++++++++++++++++++------------------------- gcc/cp/cp-tree.h | 34 +++++++++++++++++++++++++++++----- 3 files changed, 55 insertions(+), 47 deletions(-) (limited to 'gcc/cp') diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 678e120a..57bac05 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4914,10 +4914,8 @@ build_op_call_1 (tree obj, vec **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 *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 dad3849..66bc1ee 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 *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)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 368d9f5..a08867a 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. */ -- cgit v1.1