diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2008-01-13 00:17:45 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2008-01-13 00:17:45 +0000 |
commit | 7219c2c7d309f8a8f3695d82462351bb06bce542 (patch) | |
tree | 95582da2dba72b28f390915018146be99c543e93 /gcc/ada/utils.c | |
parent | 074e13552962827b93999e011156b0030b172acd (diff) | |
download | gcc-7219c2c7d309f8a8f3695d82462351bb06bce542.zip gcc-7219c2c7d309f8a8f3695d82462351bb06bce542.tar.gz gcc-7219c2c7d309f8a8f3695d82462351bb06bce542.tar.bz2 |
utils.c (aggregate_type_contains_array_p): New predicate.
* utils.c (aggregate_type_contains_array_p): New predicate.
(create_field_decl): In a packed record, force byte alignment
for fields without specified position that contain an array.
From-SVN: r131498
Diffstat (limited to 'gcc/ada/utils.c')
-rw-r--r-- | gcc/ada/utils.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c index f34816b..b158725 100644 --- a/gcc/ada/utils.c +++ b/gcc/ada/utils.c @@ -1509,6 +1509,33 @@ create_true_var_decl (tree var_name, tree asm_name, tree type, tree var_init, attr_list, gnat_node); } +/* Return true if TYPE, an aggregate type, contains (or is) an array. */ + +static bool +aggregate_type_contains_array_p (tree type) +{ + switch (TREE_CODE (type)) + { + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + { + tree field; + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + if (AGGREGATE_TYPE_P (TREE_TYPE (field)) + && aggregate_type_contains_array_p (TREE_TYPE (field))) + return true; + return false; + } + + case ARRAY_TYPE: + return true; + + default: + gcc_unreachable (); + } +} + /* Returns a FIELD_DECL node. FIELD_NAME the field name, FIELD_TYPE is its type, and RECORD_TYPE is the type of the parent. PACKED is nonzero if this field is in a record type with a "pragma pack". If SIZE is nonzero @@ -1527,8 +1554,15 @@ create_field_decl (tree field_name, tree field_type, tree record_type, TREE_READONLY (field_decl) = TYPE_READONLY (field_type); /* If FIELD_TYPE is BLKmode, we must ensure this is aligned to at least a - byte boundary since GCC cannot handle less-aligned BLKmode bitfields. */ - if (packed && TYPE_MODE (field_type) == BLKmode) + byte boundary since GCC cannot handle less-aligned BLKmode bitfields. + Likewise for an aggregate without specified position that contains an + array, because in this case slices of variable length of this array + must be handled by GCC and variable-sized objects need to be aligned + to at least a byte boundary. */ + if (packed && (TYPE_MODE (field_type) == BLKmode + || (!pos + && AGGREGATE_TYPE_P (field_type) + && aggregate_type_contains_array_p (field_type)))) DECL_ALIGN (field_decl) = BITS_PER_UNIT; /* If a size is specified, use it. Otherwise, if the record type is packed |