From patchwork Fri Nov 16 23:05:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sebor X-Patchwork-Id: 999202 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-490347-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="ZJ3GxQkO"; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="KI+HnWtH"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42xYjg4C5Lz9s3q for ; Sat, 17 Nov 2018 10:05:25 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=EHqO6MqZ/1NyGw2MKEiyHX531/d5uxT9mwQHqHnAPB7mSRKrFe sMEpO7adRFZanVlFj3408/KZkW0RUE7jUSsvoCj0yrci53UB3cJb9VCvav+hHRuv /NYKudna00cdshdTJOQL7RM3zsQUWqEKpSEbfPz9dCMy+otLM1XZq/Y+E= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=3rASWvYWIrO7DNmYtSExkirt9ko=; b=ZJ3GxQkOBZMrliKO89n1 +BiZqbQFvRlLriygaEw16pzBRO9dGTp71OM2MZORPp2dBdjd9rYEfP3Q2552c6wR gck9uQ91WUOTDL4VS+dVRO/GXTS88+4D4QTXTP0NqhZn7BkDkIdlDqp7fXV6VNla jMpcrN4HIWHQU3Gepm48HdY= Received: (qmail 44219 invoked by alias); 16 Nov 2018 23:05:18 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 44199 invoked by uid 89); 16 Nov 2018 23:05:17 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-11.1 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=contextual, dozen, lightly, Poison X-HELO: mail-qk1-f193.google.com Received: from mail-qk1-f193.google.com (HELO mail-qk1-f193.google.com) (209.85.222.193) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 16 Nov 2018 23:05:14 +0000 Received: by mail-qk1-f193.google.com with SMTP id q70so22621939qkh.6 for ; Fri, 16 Nov 2018 15:05:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:subject:message-id:date:user-agent:mime-version; bh=bUCFK3RI+Bp8aAYzNp1aGdAwM1fy4W6CEfHvf+gzBFc=; b=KI+HnWtH30/sOBssl8RFBr0Volj0J4669qep5GbpjIPceTkY59KIRNNkrHxegASPIh ujuJUWXa3ORYTR702iS6sLxKmKshXzLHybsYpSSb9jvhxE/zCIS3q5QscHZ9/sekXlJ+ +e1DrL6DXTcpmx6cMKvkjitLcyHZjjV0oIz+RdjNk4JLKkmA04WOJok+F++yg0BxXfb2 b3iTsX7IuT00pvGHM8wnZIUBVxfEq8hL5Azhsd4TlkG/POeosMdEr/0X+by0l041IP5c twqOmnaD1vrCfvYk4MjD+Rw/k3xco+O4716LnGJ+hkfcIEY2eX/R4cuL0LjY6b8ty+DA 2rbg== Received: from localhost.localdomain (184-96-239-209.hlrn.qwest.net. [184.96.239.209]) by smtp.gmail.com with ESMTPSA id v186sm1265519qkd.13.2018.11.16.15.05.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Nov 2018 15:05:10 -0800 (PST) To: Jeff Law , Gcc Patch List From: Martin Sebor Subject: [PATCH] make function_args_iterator a proper iterator Message-ID: Date: Fri, 16 Nov 2018 16:05:08 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 X-IsSubscribed: yes To encourage and simplify the adoption of iterator classes in GCC the attached patch turns the function_args_iterator struct into an (almost) proper C++ iterator class that can be used the same way as traditional forward iterators. The patch also replaces all of the 26 uses of the legacy FOREACH_FUNCTION_ARGS macro with ordinary for loops that use function_args_iterator directly, and also poisons both FOREACH_FUNCTION_ARGS and the unused FOREACH_FUNCTION_ARGS_PTR macros. The few dozen (hundred?) existing uses of for loops that iterate over function parameter types using the TREE_CHAIN() macro can be relatively easily modified to adopt the iterator approach over time. (The patch stops of short of making this change.) Eventually, when GCC moves to more a recent C++ revision, it will become possible to simplify the for loops to make use of the range based for loop syntax along the lines of: for (auto argtype: function_args (functype)) { ... } Tested on x86_64-linux, and (lightly) on powerpc64le-linux using a cross-compiler. I'll test the changes to the other back ends before committing. Martin PS For some additional background on this change see: https://gcc.gnu.org/ml/gcc-patches/2018-11/msg00493.html gcc/c/ChangeLog: * c-parser.c (check_tgmath_function): Replace FOREACH_FUNCTION_ARGS with direct function_args_iterator operations. (c_parser_postfix_expression): Same. gcc/c-family/ChangeLog: * c-ada-spec.c (dump_forward_type): Same. * c-common.c (check_function_sentinel): Same. * c-format.c (handle_format_attribute): Same. * c-warn.c (sizeof_pointer_memaccess_warning): Same. gcc/ChangeLog: * config/arm/arm.c (arm_handle_notshared_attribute): Same. (cmse_nonsecure_call_clear_caller_saved): Same. * config/i386/i386.c (init_cumulative_args): Same. * config/i386/winnt.c (gen_stdcall_or_fastcall_suffix): Same. * config/powerpcspe/powerpcspe.c (rs6000_function_parms_need_stack): Same. (rs6000_function_ok_for_sibcall): Same. * config/rs6000/rs6000.c (rs6000_function_parms_need_stack): Same. (rs6000_function_ok_for_sibcall): Same. (rs6000_mangle_decl_assembler_name): Same. * godump.c (go_format_type): Same. * tree.c (type_argument_type): Same. (get_name): Same. * tree-core.h (function_args_iterator): Move from here... * tree.h (function_args_iterator): to here. Define member and non-member functions. (FOREACH_FUNCTION_ARGS): Poison macro. (FOREACH_FUNCTION_ARGS_PTR): Poison unused macro. Index: gcc/c/c-parser.c =================================================================== --- gcc/c/c-parser.c (revision 266219) +++ gcc/c/c-parser.c (working copy) @@ -7762,14 +7762,10 @@ check_tgmath_function (c_expr *expr, unsigned int return 0; } unsigned int nargs = 0; - function_args_iterator iter; - tree t; - FOREACH_FUNCTION_ARGS (type, t, iter) - { - if (t == void_type_node) - break; - nargs++; - } + for (function_args_iterator iter (type); iter; ++iter, ++nargs) + if (*iter == void_type_node) + break; + if (nargs == 0) { error_at (expr->get_location (), @@ -8340,11 +8336,11 @@ c_parser_postfix_expression (c_parser *parser) parm_first.quick_push (first_ret); parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE); parm_varies.quick_push (false); - function_args_iterator iter; - tree t; + unsigned int argpos; - FOREACH_FUNCTION_ARGS (first_type, t, iter) + for (function_args_iterator iter (first_type); iter; ++iter) { + tree t = *iter; if (t == void_type_node) break; parm_first.quick_push (TYPE_MAIN_VARIANT (t)); @@ -8382,8 +8378,9 @@ c_parser_postfix_expression (c_parser *parser) if (TREE_CODE (ret) == COMPLEX_TYPE) parm_complex[0] = true; argpos = 1; - FOREACH_FUNCTION_ARGS (type, t, iter) + for (function_args_iterator iter (type); iter; ++iter) { + tree t = *iter; if (t == void_type_node) break; t = TYPE_MAIN_VARIANT (t); @@ -8469,8 +8466,9 @@ c_parser_postfix_expression (c_parser *parser) { tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value)); argpos = 1; - FOREACH_FUNCTION_ARGS (type, t, iter) + for (function_args_iterator iter (type); iter; ++iter) { + tree t = *iter; if (argpos == tgarg) { tg_type.quick_push (TYPE_MAIN_VARIANT (t)); @@ -8489,6 +8487,7 @@ c_parser_postfix_expression (c_parser *parser) bool all_binary = true; bool all_decimal = true; hash_set tg_types; + tree t; FOR_EACH_VEC_ELT (tg_type, i, t) { if (TREE_CODE (t) == COMPLEX_TYPE) @@ -8533,8 +8532,9 @@ c_parser_postfix_expression (c_parser *parser) goto out; } argpos = 1; - FOREACH_FUNCTION_ARGS (type, t, iter) + for (function_args_iterator iter (type); iter; ++iter) { + tree t = *iter; if (t == void_type_node) break; t = TYPE_MAIN_VARIANT (t); Index: gcc/c-family/c-ada-spec.c =================================================================== --- gcc/c-family/c-ada-spec.c (revision 266219) +++ gcc/c-family/c-ada-spec.c (working copy) @@ -2411,11 +2411,9 @@ dump_forward_type (pretty_printer *buffer, tree ty dump_forward_type (buffer, TREE_TYPE (type), t, spc); else if (TREE_CODE (type) == FUNCTION_TYPE) { - function_args_iterator args_iter; - tree arg; dump_forward_type (buffer, TREE_TYPE (type), t, spc); - FOREACH_FUNCTION_ARGS (type, arg, args_iter) - dump_forward_type (buffer, arg, t, spc); + for (function_args_iterator iter (type); iter; ++iter) + dump_forward_type (buffer, *iter, t, spc); } return; } Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 266219) +++ gcc/c-family/c-common.c (working copy) @@ -5309,11 +5309,9 @@ check_function_sentinel (const_tree fntype, int na int len = 0; int pos = 0; tree sentinel; - function_args_iterator iter; - tree t; /* Skip over the named arguments. */ - FOREACH_FUNCTION_ARGS (fntype, t, iter) + for (function_args_iterator iter (fntype); iter; ++iter) { if (len == nargs) break; Index: gcc/c-family/c-format.c =================================================================== --- gcc/c-family/c-format.c (revision 266219) +++ gcc/c-family/c-format.c (working copy) @@ -179,18 +179,17 @@ static bool check_format_string (const_tree fntype, unsigned HOST_WIDE_INT format_num, int flags, bool *no_add_attrs, int expected_format_type) { - unsigned HOST_WIDE_INT i; bool is_objc_sref, is_target_sref, is_char_ref; - tree ref; int fmt_flags; - function_args_iterator iter; - i = 1; - FOREACH_FUNCTION_ARGS (fntype, ref, iter) + tree ref = NULL_TREE; + unsigned HOST_WIDE_INT i = 1; + for (function_args_iterator iter (fntype); iter; ++iter, ++i) { + ref = *iter; + if (i == format_num) break; - i++; } if (!ref @@ -4180,12 +4179,10 @@ handle_format_attribute (tree *node, tree atname, if (info.first_arg_num != 0) { unsigned HOST_WIDE_INT arg_num = 1; - function_args_iterator iter; - tree arg_type; /* Verify that first_arg_num points to the last arg, the ... */ - FOREACH_FUNCTION_ARGS (type, arg_type, iter) + for (function_args_iterator iter (type); iter; ++iter) arg_num++; if (arg_num != info.first_arg_num) Index: gcc/c-family/c-warn.c =================================================================== --- gcc/c-family/c-warn.c (revision 266219) +++ gcc/c-family/c-warn.c (working copy) @@ -1012,12 +1012,11 @@ sizeof_pointer_memaccess_warning (location_t *size void check_main_parameter_types (tree decl) { - function_args_iterator iter; - tree type; int argct = 0; - FOREACH_FUNCTION_ARGS (TREE_TYPE (decl), type, iter) + for (function_args_iterator iter (TREE_TYPE (decl)); iter; ++iter) { + tree type = *iter; /* XXX void_type_node belies the abstraction. */ if (type == void_type_node || type == error_mark_node) break; Index: gcc/config/arm/arm.c =================================================================== --- gcc/config/arm/arm.c (revision 266219) +++ gcc/config/arm/arm.c (working copy) @@ -6945,17 +6945,17 @@ arm_handle_notshared_attribute (tree *node, static bool cmse_func_args_or_return_in_stack (tree fndecl, tree name, tree fntype) { - function_args_iterator args_iter; CUMULATIVE_ARGS args_so_far_v; cumulative_args_t args_so_far; bool first_param = true; - tree arg_type, prev_arg_type = NULL_TREE, ret_type; + tree prev_arg_type = NULL_TREE, ret_type; /* Error out if any argument is passed on the stack. */ arm_init_cumulative_args (&args_so_far_v, fntype, NULL_RTX, fndecl); args_so_far = pack_cumulative_args (&args_so_far_v); - FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) + for (function_args_iterator iter (fntype); iter; ++iter) { + tree arg_type = *iter; rtx arg_rtx; machine_mode arg_mode = TYPE_MODE (arg_type); @@ -17233,7 +17233,6 @@ cmse_nonsecure_call_clear_caller_saved (void) cumulative_args_t args_so_far; tree arg_type, fntype; bool first_param = true; - function_args_iterator args_iter; uint32_t padding_bits_to_clear[4] = {0U, 0U, 0U, 0U}; if (!NONDEBUG_INSN_P (insn)) @@ -17299,8 +17298,9 @@ cmse_nonsecure_call_clear_caller_saved (void) arm_init_cumulative_args (&args_so_far_v, fntype, NULL_RTX, NULL_TREE); args_so_far = pack_cumulative_args (&args_so_far_v); - FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) + for (function_args_iterator iter (fntype); iter; ++iter) { + tree arg_type = *iter; rtx arg_rtx; uint64_t to_clear_args_mask; machine_mode arg_mode = TYPE_MODE (arg_type); Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c (revision 266219) +++ gcc/config/i386/i386.c (working copy) @@ -7074,11 +7074,10 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Ar cum->warn_empty = !warn_abi || cum->stdarg; if (!cum->warn_empty && fntype) { - function_args_iterator iter; - tree argtype; bool seen_empty_type = false; - FOREACH_FUNCTION_ARGS (fntype, argtype, iter) + for (function_args_iterator iter (fntype); iter; ++iter) { + tree argtype = *iter; if (argtype == error_mark_node || VOID_TYPE_P (argtype)) break; if (TYPE_EMPTY_P (argtype)) Index: gcc/config/i386/winnt.c =================================================================== --- gcc/config/i386/winnt.c (revision 266219) +++ gcc/config/i386/winnt.c (working copy) @@ -182,8 +182,6 @@ gen_stdcall_or_fastcall_suffix (tree decl, tree id const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl)); char *new_str, *p; tree type = TREE_TYPE (DECL_ORIGIN (decl)); - tree arg; - function_args_iterator args_iter; gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); @@ -195,8 +193,9 @@ gen_stdcall_or_fastcall_suffix (tree decl, tree id /* Quit if we hit an incomplete type. Error is reported by convert_arguments in c-typeck.c or cp/typeck.c. */ - FOREACH_FUNCTION_ARGS(type, arg, args_iter) + for (function_args_iterator iter (type); iter; ++iter) { + tree arg = *iter; HOST_WIDE_INT parm_size; HOST_WIDE_INT parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT; Index: gcc/config/powerpcspe/powerpcspe.c =================================================================== --- gcc/config/powerpcspe/powerpcspe.c (revision 266219) +++ gcc/config/powerpcspe/powerpcspe.c (working copy) @@ -13541,11 +13541,8 @@ rs6000_function_parms_need_stack (tree fun, bool i } else { - function_args_iterator args_iter; - tree arg_type; - - FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) - if (rs6000_parm_needs_stack (args_so_far, arg_type)) + for (function_args_iterator iter (fntype); iter; ++iter) + if (rs6000_parm_needs_stack (args_so_far, *iter)) return true; } @@ -28037,22 +28034,27 @@ rs6000_function_ok_for_sibcall (tree decl, tree ex && TARGET_ALTIVEC_VRSAVE && !(decl && decl == current_function_decl)) { - function_args_iterator args_iter; - tree type; int nvreg = 0; /* Functions with vector parameters are required to have a prototype, so the argument type info must be available here. */ - FOREACH_FUNCTION_ARGS(fntype, type, args_iter) - if (TREE_CODE (type) == VECTOR_TYPE - && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type))) - nvreg++; + for (function_args_iterator iter (fntype); iter; ++iter) + { + tree type = *iter; + if (TREE_CODE (type) == VECTOR_TYPE + && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type))) + nvreg++; + } - FOREACH_FUNCTION_ARGS(TREE_TYPE (current_function_decl), type, args_iter) - if (TREE_CODE (type) == VECTOR_TYPE - && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type))) - nvreg--; + for (function_args_iterator iter (TREE_TYPE (current_function_decl)); + iter; ++iter) + { + tree type = *iter; + if (TREE_CODE (type) == VECTOR_TYPE + && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type))) + nvreg--; + } if (nvreg > 0) return false; Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 266219) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -12288,11 +12288,8 @@ rs6000_function_parms_need_stack (tree fun, bool i } else { - function_args_iterator args_iter; - tree arg_type; - - FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) - if (rs6000_parm_needs_stack (args_so_far, arg_type)) + for (function_args_iterator iter (fntype); iter; ++iter) + if (rs6000_parm_needs_stack (args_so_far, *iter)) return true; } @@ -24569,15 +24566,22 @@ rs6000_function_ok_for_sibcall (tree decl, tree ex /* Functions with vector parameters are required to have a prototype, so the argument type info must be available here. */ - FOREACH_FUNCTION_ARGS(fntype, type, args_iter) - if (TREE_CODE (type) == VECTOR_TYPE - && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type))) - nvreg++; + for (function_args_iterator iter (fntype); iter; ++iter) + { + tree type = *iter; + if (TREE_CODE (type) == VECTOR_TYPE + && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type))) + nvreg++; + } - FOREACH_FUNCTION_ARGS(TREE_TYPE (current_function_decl), type, args_iter) - if (TREE_CODE (type) == VECTOR_TYPE - && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type))) - nvreg--; + for (function_args_iterator iter (TREE_TYPE (current_function_decl)); + iter; ++iter) + { + tree type = *iter; + if (TREE_CODE (type) == VECTOR_TYPE + && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type))) + nvreg--; + } if (nvreg > 0) return false; @@ -38996,13 +39000,11 @@ rs6000_mangle_decl_assembler_name (tree decl, tree uses_ieee128_p = true; else { - function_args_iterator args_iter; - tree arg; - /* See if the function passes a IEEE 128-bit floating point type or complex type. */ - FOREACH_FUNCTION_ARGS (type, arg, args_iter) + for (function_args_iterator iter (type); iter; ++iter) { + tree arg = *iter; machine_mode arg_mode = TYPE_MODE (arg); if (arg_mode == TFmode || arg_mode == TCmode) { Index: gcc/godump.c =================================================================== --- gcc/godump.c (revision 266219) +++ gcc/godump.c (working copy) @@ -1032,10 +1032,8 @@ go_format_type (struct godump_container *container case FUNCTION_TYPE: { - tree arg_type; bool is_varargs; tree result; - function_args_iterator iter; bool seen_arg; /* Go has no way to write a type which is a function but not a @@ -1049,8 +1047,9 @@ go_format_type (struct godump_container *container obstack_1grow (ob, '('); is_varargs = stdarg_p (type); seen_arg = false; - FOREACH_FUNCTION_ARGS (type, arg_type, iter) + for (function_args_iterator iter (type); iter; ++iter) { + tree arg_type = *iter; if (VOID_TYPE_P (arg_type)) break; if (seen_arg) Index: gcc/tree-core.h =================================================================== --- gcc/tree-core.h (revision 266219) +++ gcc/tree-core.h (working copy) @@ -2042,11 +2042,6 @@ typedef struct record_layout_info_s { int packed_maybe_necessary; } *record_layout_info; -/* Iterator for going through the function arguments. */ -struct function_args_iterator { - tree next; /* TREE_LIST pointing to the next argument */ -}; - /* Structures to map from a tree to another tree. */ struct GTY(()) tree_map_base { tree from; Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 266219) +++ gcc/tree.c (working copy) @@ -6972,12 +6972,11 @@ type_argument_type (const_tree fntype, unsigned ar if (!argno) return void_type_node; - function_args_iterator iter; - - tree argtype; unsigned i = 1; - FOREACH_FUNCTION_ARGS (fntype, argtype, iter) + for (function_args_iterator iter (fntype); iter; ++iter, ++i) { + tree argtype = *iter; + /* A vararg function's argument list ends in a null. Otherwise, an ordinary function's argument list ends with void. Return null if ARGNO refers to a vararg argument, void_type_node if @@ -6987,8 +6986,6 @@ type_argument_type (const_tree fntype, unsigned ar if (i == argno || VOID_TYPE_P (argtype)) return argtype; - - ++i; } return NULL_TREE; @@ -12223,22 +12220,15 @@ get_name (tree t) } } -/* Return true if TYPE has a variable argument list. */ +/* Return true if FNTYPE has a variable argument list. */ bool stdarg_p (const_tree fntype) { - function_args_iterator args_iter; - tree n = NULL_TREE, t; + tree n = NULL_TREE; + for (function_args_iterator iter (fntype); iter; ++iter) + n = *iter; - if (!fntype) - return false; - - FOREACH_FUNCTION_ARGS (fntype, t, args_iter) - { - n = t; - } - return n != NULL_TREE && n != void_type_node; } Index: gcc/tree.h =================================================================== --- gcc/tree.h (revision 266219) +++ gcc/tree.h (working copy) @@ -4758,6 +4758,73 @@ extern tree decl_type_context (const_tree); /* Return true if EXPR is the real constant zero. */ extern bool real_zerop (const_tree); + +/* Forward iterator for iterating over the types of a function's argument + list. */ + +struct function_args_iterator +{ + tree next; /* TREE_LIST pointing to the next argument */ + + /* Create an end iterator. */ + function_args_iterator () + : next (NULL_TREE) + { /* No-op. */ } + + /* Create an iterator from a function type, or the end iterator + if FNTYPE is null. */ + function_args_iterator (const_tree fntype) + : next (fntype ? TYPE_ARG_TYPES (fntype) : NULL_TREE) + { /* No-op. */ } + + /* Contextual conversion to bool. */ + /* explicit (in C++ 11) */ operator bool () const + { + return next != NULL_TREE; + } + + /* Dereference the iterator and return a reference to the type. */ + tree& operator* () + { + return TREE_VALUE (next); + } + + /* Dereference the const iterator and return the type value. */ + tree operator* () const + { + return TREE_VALUE (next); + } + + /* Preincrement. */ + function_args_iterator& operator++ () + { + next = TREE_CHAIN (next); + return *this; + } + + /* Postincrement. */ + function_args_iterator operator++ (int) + { + const function_args_iterator tmp (*this); + ++*this; + return tmp; + } +}; + +inline bool +operator== (const function_args_iterator &lhs, + const function_args_iterator &rhs) +{ + return lhs.next == rhs.next; +} + +inline bool +operator!= (const function_args_iterator &lhs, + const function_args_iterator &rhs) +{ + return lhs.next != rhs.next; +} + /* Initialize the iterator I with arguments from function FNDECL */ static inline void @@ -4800,22 +4867,11 @@ inlined_function_outer_scope_p (const_tree block) return LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (block)) != UNKNOWN_LOCATION; } -/* Loop over all function arguments of FNTYPE. In each iteration, PTR is set - to point to the next tree element. ITER is an instance of - function_args_iterator used to iterate the arguments. */ -#define FOREACH_FUNCTION_ARGS_PTR(FNTYPE, PTR, ITER) \ - for (function_args_iter_init (&(ITER), (FNTYPE)); \ - (PTR = function_args_iter_cond_ptr (&(ITER))) != NULL; \ - function_args_iter_next (&(ITER))) +/* Use function_args_iterator directly to loop over the types of function + parameters. */ +#pragma GCC poison FOREACH_FUNCTION_ARGS +#pragma GCC poison FOREACH_FUNCTION_ARGS_PTR -/* Loop over all function arguments of FNTYPE. In each iteration, TREE is set - to the next tree element. ITER is an instance of function_args_iterator - used to iterate the arguments. */ -#define FOREACH_FUNCTION_ARGS(FNTYPE, TREE, ITER) \ - for (function_args_iter_init (&(ITER), (FNTYPE)); \ - (TREE = function_args_iter_cond (&(ITER))) != NULL_TREE; \ - function_args_iter_next (&(ITER))) - /* In tree.c */ extern unsigned crc32_unsigned_n (unsigned, unsigned, unsigned); extern unsigned crc32_string (unsigned, const char *);