Commit 8e51619a by Jason Merrill Committed by Jason Merrill

function.c (assign_parms): Handle frontend-directed pass by invisible reference.

        * 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.

From-SVN: r55781
parent 8a7f132d
2002-07-26 Jason Merrill <jason@redhat.com>
* function.c (assign_parms): Handle frontend-directed pass by
invisible reference.
2002-07-26 Neil Booth <neil@daikokuya.co.uk> 2002-07-26 Neil Booth <neil@daikokuya.co.uk>
* doc/cppopts.texi: Update. * doc/cppopts.texi: Update.
......
2002-07-26 Jason Merrill <jason@redhat.com>
* 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.
2002-07-26 Neil Booth <neil@daikokuya.co.uk> 2002-07-26 Neil Booth <neil@daikokuya.co.uk>
* cp-tree.h (flag_operator_names): Remove. * cp-tree.h (flag_operator_names): Remove.
......
...@@ -4128,15 +4128,60 @@ convert_default_arg (type, arg, fn, parmnum) ...@@ -4128,15 +4128,60 @@ convert_default_arg (type, arg, fn, parmnum)
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
"default argument", fn, parmnum); "default argument", fn, parmnum);
if (PROMOTE_PROTOTYPES arg = convert_for_arg_passing (type, arg);
&& INTEGRAL_TYPE_P (type)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
arg = default_conversion (arg);
} }
return 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)))
value = build_indirect_ref (value, NULL);
return value;
}
/* Subroutine of the various build_*_call functions. Overload resolution /* Subroutine of the various build_*_call functions. Overload resolution
has chosen a winning candidate CAND; build up a CALL_EXPR accordingly. 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 ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
...@@ -4222,10 +4267,7 @@ build_over_call (cand, args, flags) ...@@ -4222,10 +4267,7 @@ build_over_call (cand, args, flags)
val = convert_like_with_context val = convert_like_with_context
(conv, TREE_VALUE (arg), fn, i - is_method); (conv, TREE_VALUE (arg), fn, i - is_method);
if (PROMOTE_PROTOTYPES val = convert_for_arg_passing (type, val);
&& 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); converted_args = tree_cons (NULL_TREE, val, converted_args);
} }
......
...@@ -120,6 +120,9 @@ static bool cxx_warn_unused_global_decl PARAMS ((tree)); ...@@ -120,6 +120,9 @@ static bool cxx_warn_unused_global_decl PARAMS ((tree));
#undef LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING #undef LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING
#define 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 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 #undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p
#undef LANG_HOOKS_TREE_INLINING_START_INLINING #undef LANG_HOOKS_TREE_INLINING_START_INLINING
......
...@@ -3679,6 +3679,9 @@ extern tree convert_default_arg PARAMS ((tree, tree, tree, int)) ...@@ -3679,6 +3679,9 @@ extern tree convert_default_arg PARAMS ((tree, tree, tree, int))
extern tree convert_arg_to_ellipsis PARAMS ((tree)); extern tree convert_arg_to_ellipsis PARAMS ((tree));
extern tree build_x_va_arg PARAMS ((tree, tree)); extern tree build_x_va_arg PARAMS ((tree, tree));
extern tree cxx_type_promotes_to PARAMS ((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 int is_properly_derived_from PARAMS ((tree, tree));
extern tree initialize_reference PARAMS ((tree, tree)); extern tree initialize_reference PARAMS ((tree, tree));
extern tree strip_top_quals PARAMS ((tree)); extern tree strip_top_quals PARAMS ((tree));
...@@ -3958,6 +3961,7 @@ extern void mark_used PARAMS ((tree)); ...@@ -3958,6 +3961,7 @@ extern void mark_used PARAMS ((tree));
extern tree handle_class_head (enum tag_types, tree, tree, tree, int, int *); extern tree handle_class_head (enum tag_types, tree, tree, tree, int, int *);
extern tree lookup_arg_dependent PARAMS ((tree, tree, tree)); extern tree lookup_arg_dependent PARAMS ((tree, tree, tree));
extern void finish_static_data_member_decl PARAMS ((tree, tree, tree, int)); 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 build_artificial_parm PARAMS ((tree, tree));
extern tree get_guard PARAMS ((tree)); extern tree get_guard PARAMS ((tree));
extern tree get_guard_cond PARAMS ((tree)); extern tree get_guard_cond PARAMS ((tree));
......
...@@ -8518,9 +8518,8 @@ start_cleanup_fn () ...@@ -8518,9 +8518,8 @@ start_cleanup_fn ()
{ {
tree parmdecl; tree parmdecl;
parmdecl = build_decl (PARM_DECL, NULL_TREE, ptr_type_node); parmdecl = cp_build_parm_decl (NULL_TREE, ptr_type_node);
DECL_CONTEXT (parmdecl) = fndecl; DECL_CONTEXT (parmdecl) = fndecl;
DECL_ARG_TYPE (parmdecl) = ptr_type_node;
TREE_USED (parmdecl) = 1; TREE_USED (parmdecl) = 1;
DECL_ARGUMENTS (fndecl) = parmdecl; DECL_ARGUMENTS (fndecl) = parmdecl;
} }
...@@ -11366,7 +11365,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -11366,7 +11365,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
for (args = TYPE_ARG_TYPES (type); args; args = TREE_CHAIN (args)) for (args = TYPE_ARG_TYPES (type); args; args = TREE_CHAIN (args))
{ {
tree decl = build_decl (PARM_DECL, NULL_TREE, TREE_VALUE (args)); tree decl = cp_build_parm_decl (NULL_TREE, TREE_VALUE (args));
TREE_CHAIN (decl) = decls; TREE_CHAIN (decl) = decls;
decls = decl; decls = decl;
...@@ -11510,17 +11509,10 @@ friend declaration requires class-key, i.e. `friend %#T'", ...@@ -11510,17 +11509,10 @@ friend declaration requires class-key, i.e. `friend %#T'",
if (decl_context == PARM) if (decl_context == PARM)
{ {
decl = build_decl (PARM_DECL, declarator, type); decl = cp_build_parm_decl (declarator, type);
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE, bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != 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) else if (decl_context == FIELD)
{ {
...@@ -12206,11 +12198,6 @@ grokparms (first_parm) ...@@ -12206,11 +12198,6 @@ grokparms (first_parm)
decl, ptr ? "pointer" : "reference", t); 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) if (!any_error && init)
init = check_default_argument (decl, init); init = check_default_argument (decl, init);
else else
......
...@@ -795,6 +795,19 @@ grok_x_components (specs) ...@@ -795,6 +795,19 @@ grok_x_components (specs)
finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t)); 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 /* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
indicated NAME. */ indicated NAME. */
...@@ -803,14 +816,11 @@ build_artificial_parm (name, type) ...@@ -803,14 +816,11 @@ build_artificial_parm (name, type)
tree name; tree name;
tree type; tree type;
{ {
tree parm; tree parm = cp_build_parm_decl (name, type);
parm = build_decl (PARM_DECL, name, type);
DECL_ARTIFICIAL (parm) = 1; DECL_ARTIFICIAL (parm) = 1;
/* All our artificial parms are implicitly `const'; they cannot be /* All our artificial parms are implicitly `const'; they cannot be
assigned to. */ assigned to. */
TREE_READONLY (parm) = 1; TREE_READONLY (parm) = 1;
DECL_ARG_TYPE (parm) = type;
return parm; return parm;
} }
...@@ -2853,16 +2863,13 @@ start_static_storage_duration_function () ...@@ -2853,16 +2863,13 @@ start_static_storage_duration_function ()
VARRAY_PUSH_TREE (ssdf_decls, ssdf_decl); VARRAY_PUSH_TREE (ssdf_decls, ssdf_decl);
/* Create the argument list. */ /* Create the argument list. */
initialize_p_decl = build_decl (PARM_DECL, initialize_p_decl = cp_build_parm_decl
get_identifier (INITIALIZE_P_IDENTIFIER), (get_identifier (INITIALIZE_P_IDENTIFIER), integer_type_node);
integer_type_node);
DECL_CONTEXT (initialize_p_decl) = ssdf_decl; DECL_CONTEXT (initialize_p_decl) = ssdf_decl;
DECL_ARG_TYPE (initialize_p_decl) = integer_type_node;
TREE_USED (initialize_p_decl) = 1; TREE_USED (initialize_p_decl) = 1;
priority_decl = build_decl (PARM_DECL, get_identifier (PRIORITY_IDENTIFIER), priority_decl = cp_build_parm_decl
integer_type_node); (get_identifier (PRIORITY_IDENTIFIER), integer_type_node);
DECL_CONTEXT (priority_decl) = ssdf_decl; DECL_CONTEXT (priority_decl) = ssdf_decl;
DECL_ARG_TYPE (priority_decl) = integer_type_node;
TREE_USED (priority_decl) = 1; TREE_USED (priority_decl) = 1;
TREE_CHAIN (initialize_p_decl) = priority_decl; TREE_CHAIN (initialize_p_decl) = priority_decl;
......
...@@ -2494,7 +2494,9 @@ build_new_1 (exp) ...@@ -2494,7 +2494,9 @@ build_new_1 (exp)
constructor, that would fix the nesting problem and we could constructor, that would fix the nesting problem and we could
do away with this complexity. But that would complicate other do away with this complexity. But that would complicate other
things; in particular, it would make it difficult to bail out things; in particular, it would make it difficult to bail out
if the allocation function returns null. */ if the allocation function returns null. Er, no, it wouldn't;
we just don't run the constructor. The standard says it's
unspecified whether or not the args are evaluated. */
if (cleanup) if (cleanup)
{ {
......
...@@ -6012,7 +6012,7 @@ tsubst_decl (t, args, type, complain) ...@@ -6012,7 +6012,7 @@ tsubst_decl (t, args, type, complain)
r = copy_node (t); r = copy_node (t);
if (DECL_TEMPLATE_PARM_P (t)) if (DECL_TEMPLATE_PARM_P (t))
SET_DECL_TEMPLATE_PARM_P (r); SET_DECL_TEMPLATE_PARM_P (r);
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r); c_apply_type_quals_to_decl (cp_type_quals (type), r);
...@@ -6023,10 +6023,9 @@ tsubst_decl (t, args, type, complain) ...@@ -6023,10 +6023,9 @@ tsubst_decl (t, args, type, complain)
complain, in_decl); complain, in_decl);
DECL_CONTEXT (r) = NULL_TREE; DECL_CONTEXT (r) = NULL_TREE;
if (!DECL_TEMPLATE_PARM_P (r) && PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type) if (!DECL_TEMPLATE_PARM_P (r))
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) DECL_ARG_TYPE (r) = type_passed_as (type);
DECL_ARG_TYPE (r) = integer_type_node;
if (TREE_CHAIN (t)) if (TREE_CHAIN (t))
TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args,
complain, TREE_CHAIN (t)); complain, TREE_CHAIN (t));
......
...@@ -3112,11 +3112,7 @@ convert_arguments (typelist, values, fndecl, flags) ...@@ -3112,11 +3112,7 @@ convert_arguments (typelist, values, fndecl, flags)
parmval = convert_for_initialization parmval = convert_for_initialization
(NULL_TREE, type, val, flags, (NULL_TREE, type, val, flags,
"argument passing", fndecl, i); "argument passing", fndecl, i);
if (PROMOTE_PROTOTYPES parmval = convert_for_arg_passing (type, parmval);
&& INTEGRAL_TYPE_P (type)
&& (TYPE_PRECISION (type)
< TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval);
} }
if (parmval == error_mark_node) if (parmval == error_mark_node)
......
...@@ -4425,6 +4425,15 @@ assign_parms (fndecl) ...@@ -4425,6 +4425,15 @@ assign_parms (fndecl)
passed_pointer = 1; passed_pointer = 1;
passed_mode = nominal_mode = Pmode; 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; promoted_mode = passed_mode;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment