summaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2010-01-21 05:49:35 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2010-01-21 05:49:35 +0000
commit8df5a43d64487d03b55a5799f17a6c465e019062 (patch)
tree3bec735a0f06546a748f8a6b206f44f1a8b31297 /gcc/function.c
parent7b2c73adda6f38cf47e61a5eede9f4c162ecc543 (diff)
downloadgcc-8df5a43d64487d03b55a5799f17a6c465e019062.tar.gz
* tree.h (TYPE_TRANSPARENT_UNION): Replace with ...
(TYPE_TRANSPARENT_AGGR): this, for union and record. * calls.c (initialize argument_information): Handle it. * c-common.c (handle_transparent_union_attribute): Use new name. * c-decl.c (finish_struct): Ditto. * c-typeck.c (type_lists_compatible_p): Ditto. (convert_for_assignment): Use new name and also handle record. * function.c (aggregate_value_p): Handle it. (pass_by_reference): Ditto. (assign_parm_data_types): Ditto. * print-tree.c (print_node): Ditto. * lto-streamer-in.c (unpack_ts_type_value_fields): Ditto. * lto-streamer-out.c (pack_ts_type_value_fields): Ditto. * tree.c (first_field): New fn. gcc/cp/ * mangle.c (write_type): Mangle transparent record as member type. * semantics.c (begin_class_definition): Recognize decimal classes and set TYPE_TRANSPARENT_AGGR. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@156106 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/gcc/function.c b/gcc/function.c
index 6314ae01a6c..f85f780e916 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -1890,6 +1890,11 @@ aggregate_value_p (const_tree exp, const_tree fntype)
if (TREE_CODE (type) == VOID_TYPE)
return 0;
+ /* If a record should be passed the same as its first (and only) member
+ don't pass it as an aggregate. */
+ if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
+ return aggregate_value_p (first_field (type), fntype);
+
/* If the front end has decided that this needs to be passed by
reference, do so. */
if ((TREE_CODE (exp) == PARM_DECL || TREE_CODE (exp) == RESULT_DECL)
@@ -2004,6 +2009,14 @@ pass_by_reference (CUMULATIVE_ARGS *ca, enum machine_mode mode,
/* GCC post 3.4 passes *all* variable sized types by reference. */
if (!TYPE_SIZE (type) || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
return true;
+
+ /* If a record type should be passed the same as its first (and only)
+ member, use the type and mode of that member. */
+ if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
+ {
+ type = TREE_TYPE (first_field (type));
+ mode = TYPE_MODE (type);
+ }
}
return targetm.calls.pass_by_reference (ca, mode, type, named_arg);
@@ -2218,12 +2231,13 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm,
passed_mode = TYPE_MODE (passed_type);
nominal_mode = TYPE_MODE (nominal_type);
- /* If the parm is to be passed as a transparent union, use the type of
- the first field for the tests below. We have already verified that
- the modes are the same. */
- if (TREE_CODE (passed_type) == UNION_TYPE
- && TYPE_TRANSPARENT_UNION (passed_type))
- passed_type = TREE_TYPE (TYPE_FIELDS (passed_type));
+ /* If the parm is to be passed as a transparent union or record, use the
+ type of the first field for the tests below. We have already verified
+ that the modes are the same. */
+ if ((TREE_CODE (passed_type) == UNION_TYPE
+ || TREE_CODE (passed_type) == RECORD_TYPE)
+ && TYPE_TRANSPARENT_AGGR (passed_type))
+ passed_type = TREE_TYPE (first_field (passed_type));
/* See if this arg was passed by invisible reference. */
if (pass_by_reference (&all->args_so_far, passed_mode,