+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>
* 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>
* cp-tree.h (flag_operator_names): Remove.
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);
+ 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)))
+ 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
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);
+ val = convert_for_arg_passing (type, val);
converted_args = tree_cons (NULL_TREE, val, converted_args);
}
#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
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 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));
{
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_ARG_TYPE (parmdecl) = ptr_type_node;
TREE_USED (parmdecl) = 1;
DECL_ARGUMENTS (fndecl) = parmdecl;
}
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;
decls = decl;
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,
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)
{
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
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. */
tree name;
tree type;
{
- tree parm;
-
- parm = build_decl (PARM_DECL, name, 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;
- DECL_ARG_TYPE (parm) = type;
return parm;
}
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);
+ initialize_p_decl = cp_build_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);
+ priority_decl = cp_build_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;
constructor, that would fix the nesting problem and we could
do away with this complexity. But that would complicate other
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)
{
r = copy_node (t);
if (DECL_TEMPLATE_PARM_P (t))
SET_DECL_TEMPLATE_PARM_P (r);
-
+
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
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 (!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));
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);
+ parmval = convert_for_arg_passing (type, parmval);
}
if (parmval == error_mark_node)
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;