summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-03 17:59:07 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-03 17:59:07 +0000
commit3cef948a814542119083003a3c35a24e036230b6 (patch)
tree23af0d377d06c888ad90b84e9d2dfa2d2421835c
parentd3677aa8096a45d135e3cbd6ed771fe706bca1fb (diff)
downloadgcc-3cef948a814542119083003a3c35a24e036230b6.tar.gz
* expr.c (get_bit_range): Add OFFSET parameter and adjust BITPOS.
Change type of BITOFFSET to signed. Make sure the lower bound of the computed range is non-negative by adjusting OFFSET and BITPOS. (expand_assignment): Adjust call to get_bit_range. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186110 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/expr.c35
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gnat.dg/pack18.adb12
-rw-r--r--gcc/testsuite/gnat.dg/pack18_pkg.ads21
5 files changed, 73 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e1fc73b86fd..e20c0e437cd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2012-04-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * expr.c (get_bit_range): Add OFFSET parameter and adjust BITPOS.
+ Change type of BITOFFSET to signed. Make sure the lower bound of
+ the computed range is non-negative by adjusting OFFSET and BITPOS.
+ (expand_assignment): Adjust call to get_bit_range.
+
2012-04-03 Sandeep Kumar Singh <Sandeep.Singh2@kpitcummins.com>
* h8300/h8300.c (h8300_current_function_monitor_function_p):
diff --git a/gcc/expr.c b/gcc/expr.c
index 56ec3fa8e2a..6caee3be7ac 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4431,19 +4431,22 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
/* In the C++ memory model, consecutive bit fields in a structure are
considered one memory location.
- Given a COMPONENT_REF EXP at bit position BITPOS, this function
+ Given a COMPONENT_REF EXP at position (BITPOS, OFFSET), this function
returns the bit range of consecutive bits in which this COMPONENT_REF
- belongs in. The values are returned in *BITSTART and *BITEND.
- If the access does not need to be restricted 0 is returned in
+ belongs. The values are returned in *BITSTART and *BITEND. *BITPOS
+ and *OFFSET may be adjusted in the process.
+
+ If the access does not need to be restricted, 0 is returned in both
*BITSTART and *BITEND. */
static void
get_bit_range (unsigned HOST_WIDE_INT *bitstart,
unsigned HOST_WIDE_INT *bitend,
tree exp,
- HOST_WIDE_INT bitpos)
+ HOST_WIDE_INT *bitpos,
+ tree *offset)
{
- unsigned HOST_WIDE_INT bitoffset;
+ HOST_WIDE_INT bitoffset;
tree field, repr;
gcc_assert (TREE_CODE (exp) == COMPONENT_REF);
@@ -4490,7 +4493,25 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
- tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
- *bitstart = bitpos - bitoffset;
+ /* If the adjustment is larger than bitpos, we would have a negative bit
+ position for the lower bound and this may wreak havoc later. This can
+ occur only if we have a non-null offset, so adjust offset and bitpos
+ to make the lower bound non-negative. */
+ if (bitoffset > *bitpos)
+ {
+ HOST_WIDE_INT adjust = bitoffset - *bitpos;
+
+ gcc_assert ((adjust % BITS_PER_UNIT) == 0);
+ gcc_assert (*offset != NULL_TREE);
+
+ *bitpos += adjust;
+ *offset
+ = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT));
+ *bitstart = 0;
+ }
+ else
+ *bitstart = *bitpos - bitoffset;
+
*bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1;
}
@@ -4595,7 +4616,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
if (TREE_CODE (to) == COMPONENT_REF
&& DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
- get_bit_range (&bitregion_start, &bitregion_end, to, bitpos);
+ get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset);
/* If we are going to use store_bit_field and extract_bit_field,
make sure to_rtx will be safe for multiple use. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c757d42d177..ca5c35adce8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-04-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/pack18.adb: New test.
+ * gnat.dg/pack18_pkg.ads: New helper.
+
2012-04-03 Richard Guenther <rguenther@suse.de>
PR tree-optimization/52808
diff --git a/gcc/testsuite/gnat.dg/pack18.adb b/gcc/testsuite/gnat.dg/pack18.adb
new file mode 100644
index 00000000000..857a6f9787e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/pack18.adb
@@ -0,0 +1,12 @@
+-- { dg-do run }
+
+with Pack18_Pkg; use Pack18_Pkg;
+
+procedure Pack18 is
+ use Pack18_Pkg.Attributes_Tables;
+ Table : Instance;
+begin
+ Init (Table);
+ Set_Last (Table, 1);
+ Table.Table (Last (Table)).N := 0;
+end;
diff --git a/gcc/testsuite/gnat.dg/pack18_pkg.ads b/gcc/testsuite/gnat.dg/pack18_pkg.ads
new file mode 100644
index 00000000000..2b63fbab063
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/pack18_pkg.ads
@@ -0,0 +1,21 @@
+with GNAT.Dynamic_Tables;
+
+package Pack18_Pkg is
+
+ type String_Access is access String;
+
+ type Rec is record
+ S : String_Access;
+ B : Boolean;
+ N : Natural;
+ end record;
+ pragma Pack (Rec);
+
+ package Attributes_Tables is new GNAT.Dynamic_Tables
+ (Table_Component_Type => Rec,
+ Table_Index_Type => Natural,
+ Table_Low_Bound => 1,
+ Table_Initial => 200,
+ Table_Increment => 200);
+
+end Pack18_Pkg;