utils.c (aggregate_type_contains_array_p): New predicate.
authorEric Botcazou <ebotcazou@adacore.com>
Sun, 13 Jan 2008 00:17:45 +0000 (00:17 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sun, 13 Jan 2008 00:17:45 +0000 (00:17 +0000)
* 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

gcc/ada/ChangeLog
gcc/ada/utils.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/slice3.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/slice4.adb [new file with mode: 0644]

index 7b1745cffa9ed241f497ce7d8f5d2c718dec266a..d1bedccbd9b7795f9f77f23bfc2f6e3abbed08bd 100644 (file)
@@ -1,3 +1,9 @@
+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.
index f34816b09d67f25849d2c1afddb6e3fdbc087dcd..b158725747704f70f2db4766fb9b665c18e064ae 100644 (file)
@@ -1509,6 +1509,33 @@ create_true_var_decl (tree var_name, tree asm_name, tree type, tree var_init,
                            attr_list, gnat_node);
 }
 \f
+/* 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
index dd1f5a1cd4078f2ac88c658e98446c719d88b423..1c7ec62cac675cbef1e75482775b89c431014059 100644 (file)
@@ -1,3 +1,8 @@
+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.
diff --git a/gcc/testsuite/gnat.dg/slice3.adb b/gcc/testsuite/gnat.dg/slice3.adb
new file mode 100644 (file)
index 0000000..db568f9
--- /dev/null
@@ -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 (file)
index 0000000..a7890a2
--- /dev/null
@@ -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;