aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/utils.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2008-01-13 00:17:45 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2008-01-13 00:17:45 +0000
commit7219c2c7d309f8a8f3695d82462351bb06bce542 (patch)
tree95582da2dba72b28f390915018146be99c543e93 /gcc/ada/utils.c
parent074e13552962827b93999e011156b0030b172acd (diff)
downloadgcc-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.c38
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