aboutsummaryrefslogtreecommitdiff
path: root/gcc
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
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')
-rw-r--r--gcc/ada/ChangeLog6
-rw-r--r--gcc/ada/utils.c38
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gnat.dg/slice3.adb24
-rw-r--r--gcc/testsuite/gnat.dg/slice4.adb28
5 files changed, 99 insertions, 2 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 7b1745c..d1bedcc 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,5 +1,11 @@
2008-01-12 Eric Botcazou <ebotcazou@adacore.com>
+ * 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.
+
+2008-01-12 Eric Botcazou <ebotcazou@adacore.com>
+
* utils.c (unchecked_convert): Fold the VIEW_CONVERT_EXPR expression.
2008-01-10 John David Anglin <dave.anglin.@nrc-cnrc.gc.ca>
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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dd1f5a1..1c7ec62 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2008-01-12 Eric Botcazou <ebotcazou@adacore.com>
+ * gnat.dg/slice3.adb: New test.
+ * gnat.dg/slice4.adb: Likewise.
+
+2008-01-12 Eric Botcazou <ebotcazou@adacore.com>
+
* gnat.dg/bit_packed_array.ad[sb]: New test.
2008-01-12 Jerry DeLisle <jvdelisle@gcc.gnu.org>
diff --git a/gcc/testsuite/gnat.dg/slice3.adb b/gcc/testsuite/gnat.dg/slice3.adb
new file mode 100644
index 0000000..db568f9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/slice3.adb
@@ -0,0 +1,24 @@
+-- { dg-do run }
+
+procedure Slice3 is
+
+ type Varray is array (1 .. 1) of Natural; -- SImode
+
+ type Sample is record
+ Maybe : Boolean;
+ Values : Varray;
+ end record;
+ pragma Pack (Sample);
+
+ function Match (X, Y: Sample; Length : Positive) return Boolean is
+ begin
+ return X.Values (1 .. Length) = Y.Values (1 .. Length);
+ end;
+
+ X, Y : Sample := (Maybe => True, Values => (1 => 1));
+begin
+ X.Maybe := False;
+ if not Match (X, Y, 1) then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/slice4.adb b/gcc/testsuite/gnat.dg/slice4.adb
new file mode 100644
index 0000000..a7890a2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/slice4.adb
@@ -0,0 +1,28 @@
+-- { dg-do run }
+
+procedure Slice4 is
+
+ type Varray is array (1 .. 1) of Natural; -- SImode
+
+ type Rec is record
+ Values : Varray;
+ end record;
+
+ type Sample is record
+ Maybe : Boolean;
+ R : Rec;
+ end record;
+ pragma Pack (Sample);
+
+ function Match (X, Y: Sample; Length : Positive) return Boolean is
+ begin
+ return X.R.Values (1 .. Length) = Y.R.Values (1 .. Length);
+ end;
+
+ X, Y : Sample := (Maybe => True, R => (Values => (1 => 1)));
+begin
+ X.Maybe := False;
+ if not Match (X, Y, 1) then
+ raise Program_Error;
+ end if;
+end;