From 73041e9b577ea9e2cb769c0ca0230ab031f08ca5 Mon Sep 17 00:00:00 2001 From: ebotcazou Date: Tue, 27 Mar 2012 10:35:55 +0000 Subject: [PATCH] * expmed.c (store_bit_field): Assert that BITREGION_START is a multiple of a unit before computing the offset in units. * expr.c (get_bit_range): Return the null range if the enclosing record is part of a larger bit field. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@185857 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 +++++++ gcc/expmed.c | 5 +++-- gcc/expr.c | 19 +++++++++++++++++++ gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gnat.dg/pack17.adb | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/pack17.adb diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8321a8e..bf370df 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2012-03-27 Eric Botcazou + + * expmed.c (store_bit_field): Assert that BITREGION_START is a multiple + of a unit before computing the offset in units. + * expr.c (get_bit_range): Return the null range if the enclosing record + is part of a larger bit field. + 2012-03-27 Tristan Gingold * config/ia64/vms.h (CASE_VECTOR_MODE): Define. diff --git a/gcc/expmed.c b/gcc/expmed.c index 5134b73..54e51dc 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -828,8 +828,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, /* Under the C++0x memory model, we must not touch bits outside the bit region. Adjust the address to start at the beginning of the bit region. */ - if (MEM_P (str_rtx) - && bitregion_start > 0) + if (MEM_P (str_rtx) && bitregion_start > 0) { enum machine_mode bestmode; enum machine_mode op_mode; @@ -839,6 +838,8 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (op_mode == MAX_MACHINE_MODE) op_mode = VOIDmode; + gcc_assert ((bitregion_start % BITS_PER_UNIT) == 0); + offset = bitregion_start / BITS_PER_UNIT; bitnum -= bitregion_start; bitregion_end -= bitregion_start; diff --git a/gcc/expr.c b/gcc/expr.c index c63343e..56ec3fa 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -4458,6 +4458,25 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart, return; } + /* If we have a DECL_BIT_FIELD_REPRESENTATIVE but the enclosing record is + part of a larger bit field, then the representative does not serve any + useful purpose. This can occur in Ada. */ + if (handled_component_p (TREE_OPERAND (exp, 0))) + { + enum machine_mode rmode; + HOST_WIDE_INT rbitsize, rbitpos; + tree roffset; + int unsignedp; + int volatilep = 0; + get_inner_reference (TREE_OPERAND (exp, 0), &rbitsize, &rbitpos, + &roffset, &rmode, &unsignedp, &volatilep, false); + if ((rbitpos % BITS_PER_UNIT) != 0) + { + *bitstart = *bitend = 0; + return; + } + } + /* Compute the adjustment to bitpos from the offset of the field relative to the representative. DECL_FIELD_OFFSET of field and repr are the same by construction if they are not constants, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e10e53d..63de5d4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-03-27 Eric Botcazou + + * gnat.dg/pack17.adb: New test. + 2012-03-27 Ramana Radhakrishnan * gcc.target/arm/thumb-ifcvt.c: Only run for -mthumb. diff --git a/gcc/testsuite/gnat.dg/pack17.adb b/gcc/testsuite/gnat.dg/pack17.adb new file mode 100644 index 0000000..2333ba7 --- /dev/null +++ b/gcc/testsuite/gnat.dg/pack17.adb @@ -0,0 +1,38 @@ +-- { dg-do run } + +procedure Pack17 is + + type Bitmap_T is array (Natural range <>) of Boolean; + pragma Pack (Bitmap_T); + + type Uint8 is range 0 .. 2 ** 8 - 1; + for Uint8'Size use 8; + + type Record_With_QImode_Variants (D : Boolean) is record + C_Filler : Bitmap_T (1..7); + C_Map : Bitmap_T (1..3); + case D is + when False => + F_Bit : Boolean; + F_Filler : Bitmap_T (1..7); + when True => + T_Int : Uint8; + end case; + end record; + pragma Pack (Record_With_QImode_Variants); + + procedure Fill (R : out Record_With_QImode_Variants) is + begin + R.C_Filler := (True, False, True, False, True, False, True); + R.C_Map := (True, False, True); + R.T_Int := 17; + end; + + RT : Record_With_QImode_Variants (D => True); + +begin + Fill (RT); + if RT.T_Int /= 17 then + raise Program_Error; + end if; +end; -- 2.7.4