summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/expr.c19
-rw-r--r--gcc/stor-layout.c35
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gnat.dg/pack16.adb26
-rw-r--r--gcc/testsuite/gnat.dg/pack16_pkg.ads5
-rw-r--r--gcc/testsuite/gnat.dg/specs/pack8.ads19
-rw-r--r--gcc/testsuite/gnat.dg/specs/pack8_pkg.ads5
8 files changed, 117 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bf9d56f6a8d..9eade87ce52 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2012-03-20 Richard Guenther <rguenther@suse.de>
+
+ * stor-layout.c (finish_bitfield_representative): Fallback
+ to conservative maximum size if the padding up to the next
+ field cannot be computed as a constant.
+ (finish_bitfield_layout): If we cannot compute the distance
+ between the start of the bitfield representative and the
+ bitfield member start a new representative.
+ * expr.c (get_bit_range): The distance between the start of
+ the bitfield representative and the bitfield member is zero
+ if the field offsets are not constants.
+
2012-03-20 Tristan Gingold <gingold@adacore.com>
* tree.h (enum size_type_kind): Add stk_ prefix to constants,
diff --git a/gcc/expr.c b/gcc/expr.c
index fcd5b36f94a..f9de9080d8b 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4452,7 +4452,7 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
HOST_WIDE_INT bitpos)
{
unsigned HOST_WIDE_INT bitoffset;
- tree field, repr, offset;
+ tree field, repr;
gcc_assert (TREE_CODE (exp) == COMPONENT_REF);
@@ -4467,12 +4467,17 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
}
/* Compute the adjustment to bitpos from the offset of the field
- relative to the representative. */
- offset = size_diffop (DECL_FIELD_OFFSET (field),
- DECL_FIELD_OFFSET (repr));
- bitoffset = (tree_low_cst (offset, 1) * BITS_PER_UNIT
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
- - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
+ relative to the representative. DECL_FIELD_OFFSET of field and
+ repr are the same by construction if they are not constants,
+ see finish_bitfield_layout. */
+ if (host_integerp (DECL_FIELD_OFFSET (field), 1)
+ && host_integerp (DECL_FIELD_OFFSET (repr), 1))
+ bitoffset = (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
+ - tree_low_cst (DECL_FIELD_OFFSET (repr), 1)) * BITS_PER_UNIT;
+ else
+ bitoffset = 0;
+ bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
+ - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
*bitstart = bitpos - bitoffset;
*bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1;
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 2d3f92e202f..d79be1424e3 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -1781,10 +1781,17 @@ finish_bitfield_representative (tree repr, tree field)
return;
maxsize = size_diffop (DECL_FIELD_OFFSET (nextf),
DECL_FIELD_OFFSET (repr));
- gcc_assert (host_integerp (maxsize, 1));
- maxbitsize = (tree_low_cst (maxsize, 1) * BITS_PER_UNIT
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (nextf), 1)
- - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
+ if (host_integerp (maxsize, 1))
+ {
+ maxbitsize = (tree_low_cst (maxsize, 1) * BITS_PER_UNIT
+ + tree_low_cst (DECL_FIELD_BIT_OFFSET (nextf), 1)
+ - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
+ /* If the group ends within a bitfield nextf does not need to be
+ aligned to BITS_PER_UNIT. Thus round up. */
+ maxbitsize = (maxbitsize + BITS_PER_UNIT - 1) & ~(BITS_PER_UNIT - 1);
+ }
+ else
+ maxbitsize = bitsize;
}
else
{
@@ -1888,6 +1895,8 @@ finish_bitfield_layout (record_layout_info rli)
}
else if (DECL_BIT_FIELD_TYPE (field))
{
+ gcc_assert (repr != NULL_TREE);
+
/* Zero-size bitfields finish off a representative and
do not have a representative themselves. This is
required by the C++ memory model. */
@@ -1896,6 +1905,24 @@ finish_bitfield_layout (record_layout_info rli)
finish_bitfield_representative (repr, prev);
repr = NULL_TREE;
}
+
+ /* We assume that either DECL_FIELD_OFFSET of the representative
+ and each bitfield member is a constant or they are equal.
+ This is because we need to be able to compute the bit-offset
+ of each field relative to the representative in get_bit_range
+ during RTL expansion.
+ If these constraints are not met, simply force a new
+ representative to be generated. That will at most
+ generate worse code but still maintain correctness with
+ respect to the C++ memory model. */
+ else if (!((host_integerp (DECL_FIELD_OFFSET (repr), 1)
+ && host_integerp (DECL_FIELD_OFFSET (field), 1))
+ || operand_equal_p (DECL_FIELD_OFFSET (repr),
+ DECL_FIELD_OFFSET (field), 0)))
+ {
+ finish_bitfield_representative (repr, prev);
+ repr = start_bitfield_representative (field);
+ }
}
else
continue;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ab0dd1d06bc..02641707476 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2012-03-20 Richard Guenther <rguenther@suse.de>
+
+ * gnat.dg/pack16.adb: New testcase.
+ * gnat.dg/pack16_pkg.ads: Likewise.
+ * gnat.dg/specs/pack8.ads: Likewise.
+ * gnat.dg/specs/pack8_pkg.ads: Likewise.
+
2012-03-19 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/warn/Wuseless-cast.C: Extend.
diff --git a/gcc/testsuite/gnat.dg/pack16.adb b/gcc/testsuite/gnat.dg/pack16.adb
new file mode 100644
index 00000000000..eb8e2f9b8d3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/pack16.adb
@@ -0,0 +1,26 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+
+with Pack16_Pkg; use Pack16_Pkg;
+
+procedure Pack16 is
+
+ type Sample_Table_T is array (1 .. N) of Integer;
+
+ type Clock_T is record
+ N_Ticks : Integer := 0;
+ end record;
+
+ type Sampling_Descriptor_T is record
+ Values : Sample_Table_T;
+ Valid : Boolean;
+ Tstamp : Clock_T;
+ end record;
+
+ pragma Pack (Sampling_Descriptor_T);
+
+ Sampling_Data : Sampling_Descriptor_T;
+
+begin
+ null;
+end;
diff --git a/gcc/testsuite/gnat.dg/pack16_pkg.ads b/gcc/testsuite/gnat.dg/pack16_pkg.ads
new file mode 100644
index 00000000000..92884f32fde
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/pack16_pkg.ads
@@ -0,0 +1,5 @@
+package Pack16_Pkg is
+
+ N : Natural := 16;
+
+end Pack16_Pkg;
diff --git a/gcc/testsuite/gnat.dg/specs/pack8.ads b/gcc/testsuite/gnat.dg/specs/pack8.ads
new file mode 100644
index 00000000000..db839cbe276
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/pack8.ads
@@ -0,0 +1,19 @@
+with Pack8_Pkg;
+
+package Pack8 is
+
+ subtype Index_Type is Integer range 1 .. Pack8_Pkg.N;
+
+ subtype Str is String( Index_Type);
+
+ subtype Str2 is String (1 .. 11);
+
+ type Rec is record
+ S1 : Str;
+ S2 : Str;
+ B : Boolean;
+ S3 : Str2;
+ end record;
+ pragma Pack (Rec);
+
+end Pack8;
diff --git a/gcc/testsuite/gnat.dg/specs/pack8_pkg.ads b/gcc/testsuite/gnat.dg/specs/pack8_pkg.ads
new file mode 100644
index 00000000000..f35e629cad8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/pack8_pkg.ads
@@ -0,0 +1,5 @@
+package Pack8_Pkg is
+
+ N : Natural := 1;
+
+end Pack8_Pkg;