From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27424 invoked by alias); 26 Jul 2002 10:04:56 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 27137 invoked from network); 26 Jul 2002 10:04:52 -0000 Received: from unknown (HELO executor.cambridge.redhat.com) (195.224.55.237) by sources.redhat.com with SMTP; 26 Jul 2002 10:04:52 -0000 Received: from prospero.cambridge.redhat.com (dell-paw-2.cambridge.redhat.com [195.224.55.226]) by executor.cambridge.redhat.com (Postfix) with ESMTP id 0CA5FABB16; Fri, 26 Jul 2002 11:04:51 +0100 (BST) Received: by prospero.cambridge.redhat.com (Postfix, from userid 4046) id 19125F8D68; Fri, 26 Jul 2002 11:04:42 +0100 (BST) To: Richard Henderson Cc: Mark Mitchell , gcc@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: PATCH Re: Simplifying TARGET_EXPR References: <20020720135854.C16252@redhat.com> From: Jason Merrill In-Reply-To: <20020720135854.C16252@redhat.com> (Richard Henderson's message of "Sat, 20 Jul 2002 13:58:54 -0700") Date: Fri, 26 Jul 2002 14:51:00 -0000 Message-ID: User-Agent: Gnus/5.090007 (Oort Gnus v0.07) Emacs/21.1 (i686-pc-linux-gnu) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-SW-Source: 2002-07/txt/msg01273.txt.bz2 --=-=-= Content-length: 1558 >>>>> "Richard" == Richard Henderson writes: > Given that the front end has to know about the semantics of copying > objects and how that affects parameter passing anyway, perhaps the > front end should modify the type of the parameter at the same time. > Perhaps a REFERENCE_TYPE with DECL_ARTIFICIAL set? Then an ADDR_EXPR > would match up nicely. It occurred to me that we already have DECL_ARG_TYPE for handling this sort of thing. This patch sets DECL_ARG_TYPE to a REFERENCE_TYPE if we want to pass by invisible reference for frontend-specific reasons. These semantics are handled by three new functions in cp/call.c; the rest of the patch is telling other bits of code to use them. Tested i686-pc-linux-gnu. I'll check this in soon if nobody complains. 2002-07-25 Jason Merrill * function.c (assign_parms): Handle frontend-directed pass by invisible reference. cp/ * call.c (build_over_call): Likewise. (cp_convert_parm_for_inlining): New fn. (convert_for_arg_passing): New fn. (convert_default_arg, build_over_call): Use it. (type_passed_as): New fn. * pt.c (tsubst_decl): Use it. * decl2.c (cp_build_parm_decl): New fn. (build_artificial_parm): Use it. (start_static_storage_duration_function): Likewise. * decl.c (start_cleanup_fn, grokdeclarater): Likewise. (grokparms): Don't mess with DECL_ARG_TYPE. * typeck.c (convert_arguments): Use convert_for_arg_passing. * cp-lang.c (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING): Define. * cp-tree.h: Declare new fns. --=-=-= Content-Type: text/x-patch Content-Disposition: inline Content-length: 12744 *** ./cp/pt.c.~1~ Wed Jul 24 12:40:22 2002 --- ./cp/pt.c Wed Jul 24 12:35:50 2002 *************** tsubst_decl (t, args, type, complain) *** 6023,6032 **** complain, in_decl); DECL_CONTEXT (r) = NULL_TREE; ! if (!DECL_TEMPLATE_PARM_P (r) && PROMOTE_PROTOTYPES ! && INTEGRAL_TYPE_P (type) ! && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) ! DECL_ARG_TYPE (r) = integer_type_node; if (TREE_CHAIN (t)) TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, complain, TREE_CHAIN (t)); --- 6023,6031 ---- complain, in_decl); DECL_CONTEXT (r) = NULL_TREE; ! ! if (!DECL_TEMPLATE_PARM_P (r)) ! DECL_ARG_TYPE (r) = type_passed_as (type); if (TREE_CHAIN (t)) TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, complain, TREE_CHAIN (t)); *** ./cp/call.c.~1~ Wed Jul 24 12:40:22 2002 --- ./cp/call.c Wed Jul 24 17:10:12 2002 *************** convert_default_arg (type, arg, fn, parm *** 4128,4142 **** arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, "default argument", fn, parmnum); ! if (PROMOTE_PROTOTYPES ! && INTEGRAL_TYPE_P (type) ! && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) ! arg = default_conversion (arg); } return arg; } /* Subroutine of the various build_*_call functions. Overload resolution has chosen a winning candidate CAND; build up a CALL_EXPR accordingly. ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a --- 4128,4191 ---- arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, "default argument", fn, parmnum); ! arg = convert_for_arg_passing (type, arg); } return arg; } + /* Returns the type which will really be used for passing an argument of + type TYPE. */ + + tree + type_passed_as (type) + tree type; + { + /* Pass classes with copy ctors by invisible reference. */ + if (TREE_ADDRESSABLE (type)) + type = build_reference_type (type); + else if (PROMOTE_PROTOTYPES + && INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) + type = integer_type_node; + + return type; + } + + /* Actually perform the appropriate conversion. */ + + tree + convert_for_arg_passing (type, val) + tree type, val; + { + /* Pass classes with copy ctors by invisible reference. */ + if (TREE_ADDRESSABLE (type)) + val = build1 (ADDR_EXPR, build_reference_type (type), val); + else if (PROMOTE_PROTOTYPES + && INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) + val = default_conversion (val); + return val; + } + + /* Convert VALUE for assignment into inlined parameter PARM. */ + + tree + cp_convert_parm_for_inlining (parm, value, fn) + tree parm, value; + tree fn ATTRIBUTE_UNUSED; + { + /* When inlining, we don't need to mess with invisible references, so + undo the ADDR_EXPR. */ + if (TREE_ADDRESSABLE (TREE_TYPE (parm))) + { + if (TREE_TYPE (value) != build_reference_type (TREE_TYPE (parm))) + abort (); + value = build_indirect_ref (value, NULL); + } + return value; + } + /* Subroutine of the various build_*_call functions. Overload resolution has chosen a winning candidate CAND; build up a CALL_EXPR accordingly. ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a *************** build_over_call (cand, args, flags) *** 4222,4231 **** val = convert_like_with_context (conv, TREE_VALUE (arg), fn, i - is_method); ! if (PROMOTE_PROTOTYPES ! && INTEGRAL_TYPE_P (type) ! && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) ! val = default_conversion (val); converted_args = tree_cons (NULL_TREE, val, converted_args); } --- 4271,4277 ---- val = convert_like_with_context (conv, TREE_VALUE (arg), fn, i - is_method); ! val = convert_for_arg_passing (type, val); converted_args = tree_cons (NULL_TREE, val, converted_args); } *** ./cp/decl.c.~1~ Wed Jul 24 12:40:22 2002 --- ./cp/decl.c Wed Jul 24 12:35:46 2002 *************** start_cleanup_fn () *** 8518,8526 **** { tree parmdecl; ! parmdecl = build_decl (PARM_DECL, NULL_TREE, ptr_type_node); DECL_CONTEXT (parmdecl) = fndecl; - DECL_ARG_TYPE (parmdecl) = ptr_type_node; TREE_USED (parmdecl) = 1; DECL_ARGUMENTS (fndecl) = parmdecl; } --- 8518,8525 ---- { tree parmdecl; ! parmdecl = cp_build_parm_decl (NULL_TREE, ptr_type_node); DECL_CONTEXT (parmdecl) = fndecl; TREE_USED (parmdecl) = 1; DECL_ARGUMENTS (fndecl) = parmdecl; } *************** grokdeclarator (declarator, declspecs, d *** 11366,11372 **** for (args = TYPE_ARG_TYPES (type); args; args = TREE_CHAIN (args)) { ! tree decl = build_decl (PARM_DECL, NULL_TREE, TREE_VALUE (args)); TREE_CHAIN (decl) = decls; decls = decl; --- 11365,11371 ---- for (args = TYPE_ARG_TYPES (type); args; args = TREE_CHAIN (args)) { ! tree decl = cp_build_parm_decl (NULL_TREE, TREE_VALUE (args)); TREE_CHAIN (decl) = decls; decls = decl; *************** friend declaration requires class-key, i *** 11510,11526 **** if (decl_context == PARM) { ! decl = build_decl (PARM_DECL, declarator, type); bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); - - /* Compute the type actually passed in the parmlist, - for the case where there is no prototype. - (For example, shorts and chars are passed as ints.) - When there is a prototype, this is overridden later. */ - - DECL_ARG_TYPE (decl) = type_promotes_to (type); } else if (decl_context == FIELD) { --- 11509,11518 ---- if (decl_context == PARM) { ! decl = cp_build_parm_decl (declarator, type); bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE, inlinep, friendp, raises != NULL_TREE); } else if (decl_context == FIELD) { *************** grokparms (first_parm) *** 12206,12216 **** decl, ptr ? "pointer" : "reference", t); } - DECL_ARG_TYPE (decl) = TREE_TYPE (decl); - if (PROMOTE_PROTOTYPES - && INTEGRAL_TYPE_P (type) - && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (decl) = integer_type_node; if (!any_error && init) init = check_default_argument (decl, init); else --- 12198,12203 ---- *** ./cp/cp-lang.c.~1~ Wed Jul 24 12:40:22 2002 --- ./cp/cp-lang.c Tue Jul 23 17:53:41 2002 *************** static bool cxx_warn_unused_global_decl *** 120,125 **** --- 120,128 ---- #undef LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING #define LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING \ cp_copy_res_decl_for_inlining + #undef LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING + #define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \ + cp_convert_parm_for_inlining #undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p #undef LANG_HOOKS_TREE_INLINING_START_INLINING *** ./cp/cp-tree.h.~1~ Wed Jul 24 12:40:22 2002 --- ./cp/cp-tree.h Wed Jul 24 17:09:43 2002 *************** extern tree convert_default_arg *** 3683,3688 **** --- 3683,3691 ---- extern tree convert_arg_to_ellipsis PARAMS ((tree)); extern tree build_x_va_arg PARAMS ((tree, tree)); extern tree cxx_type_promotes_to PARAMS ((tree)); + extern tree type_passed_as PARAMS ((tree)); + extern tree convert_for_arg_passing PARAMS ((tree, tree)); + extern tree cp_convert_parm_for_inlining PARAMS ((tree, tree, tree)); extern int is_properly_derived_from PARAMS ((tree, tree)); extern tree initialize_reference PARAMS ((tree, tree)); extern tree strip_top_quals PARAMS ((tree)); *************** extern void mark_used PARAMS ((tree)) *** 3962,3967 **** --- 3965,3971 ---- extern tree handle_class_head (enum tag_types, tree, tree, tree, int, int *); extern tree lookup_arg_dependent PARAMS ((tree, tree, tree)); extern void finish_static_data_member_decl PARAMS ((tree, tree, tree, int)); + extern tree cp_build_parm_decl PARAMS ((tree, tree)); extern tree build_artificial_parm PARAMS ((tree, tree)); extern tree get_guard PARAMS ((tree)); extern tree get_guard_cond PARAMS ((tree)); *** ./cp/decl2.c.~1~ Wed Jul 24 12:40:22 2002 --- ./cp/decl2.c Wed Jul 24 12:35:47 2002 *************** grok_x_components (specs) *** 808,813 **** --- 808,826 ---- finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t)); } + /* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE + appropriately. */ + + tree + cp_build_parm_decl (name, type) + tree name; + tree type; + { + tree parm = build_decl (PARM_DECL, name, type); + DECL_ARG_TYPE (parm) = type_passed_as (type); + return parm; + } + /* Returns a PARM_DECL for a parameter of the indicated TYPE, with the indicated NAME. */ *************** build_artificial_parm (name, type) *** 816,829 **** tree name; tree type; { ! tree parm; ! ! parm = build_decl (PARM_DECL, name, type); DECL_ARTIFICIAL (parm) = 1; /* All our artificial parms are implicitly `const'; they cannot be assigned to. */ TREE_READONLY (parm) = 1; - DECL_ARG_TYPE (parm) = type; return parm; } --- 829,839 ---- tree name; tree type; { ! tree parm = cp_build_parm_decl (name, type); DECL_ARTIFICIAL (parm) = 1; /* All our artificial parms are implicitly `const'; they cannot be assigned to. */ TREE_READONLY (parm) = 1; return parm; } *************** start_static_storage_duration_function ( *** 2866,2881 **** VARRAY_PUSH_TREE (ssdf_decls, ssdf_decl); /* Create the argument list. */ ! initialize_p_decl = build_decl (PARM_DECL, ! get_identifier (INITIALIZE_P_IDENTIFIER), ! integer_type_node); DECL_CONTEXT (initialize_p_decl) = ssdf_decl; - DECL_ARG_TYPE (initialize_p_decl) = integer_type_node; TREE_USED (initialize_p_decl) = 1; ! priority_decl = build_decl (PARM_DECL, get_identifier (PRIORITY_IDENTIFIER), ! integer_type_node); DECL_CONTEXT (priority_decl) = ssdf_decl; - DECL_ARG_TYPE (priority_decl) = integer_type_node; TREE_USED (priority_decl) = 1; TREE_CHAIN (initialize_p_decl) = priority_decl; --- 2876,2888 ---- VARRAY_PUSH_TREE (ssdf_decls, ssdf_decl); /* Create the argument list. */ ! initialize_p_decl = cp_build_parm_decl ! (get_identifier (INITIALIZE_P_IDENTIFIER), integer_type_node); DECL_CONTEXT (initialize_p_decl) = ssdf_decl; TREE_USED (initialize_p_decl) = 1; ! priority_decl = cp_build_parm_decl ! (get_identifier (PRIORITY_IDENTIFIER), integer_type_node); DECL_CONTEXT (priority_decl) = ssdf_decl; TREE_USED (priority_decl) = 1; TREE_CHAIN (initialize_p_decl) = priority_decl; *** ./cp/typeck.c.~1~ Wed Jul 24 12:40:22 2002 --- ./cp/typeck.c Wed Jul 24 17:04:54 2002 *************** convert_arguments (typelist, values, fnd *** 3145,3155 **** parmval = convert_for_initialization (NULL_TREE, type, val, flags, "argument passing", fndecl, i); ! if (PROMOTE_PROTOTYPES ! && INTEGRAL_TYPE_P (type) ! && (TYPE_PRECISION (type) ! < TYPE_PRECISION (integer_type_node))) ! parmval = default_conversion (parmval); } if (parmval == error_mark_node) --- 3145,3151 ---- parmval = convert_for_initialization (NULL_TREE, type, val, flags, "argument passing", fndecl, i); ! parmval = convert_for_arg_passing (type, parmval); } if (parmval == error_mark_node) *** ./function.c.~1~ Wed Jul 24 12:40:22 2002 --- ./function.c Wed Jul 24 12:35:18 2002 *************** assign_parms (fndecl) *** 4425,4430 **** --- 4425,4439 ---- passed_pointer = 1; passed_mode = nominal_mode = Pmode; } + /* See if the frontend wants to pass this by invisible reference. */ + else if (passed_type != nominal_type + && POINTER_TYPE_P (passed_type) + && TREE_TYPE (passed_type) == nominal_type) + { + nominal_type = passed_type; + passed_pointer = 1; + passed_mode = nominal_mode = Pmode; + } promoted_mode = passed_mode; --=-=-=--