Fix handling of non-integral bit-fields in native_encode_initializer
The encoder for CONSTRUCTORs assumes that all bit-fields (DECL_BIT_FIELD) have integral types, but that's not the case in Ada where they may have pretty much any type, resulting in a wrong encoding for them gcc/ * fold-const.cc (native_encode_initializer) <CONSTRUCTOR>: Apply the specific treatment for bit-fields only if they have an integral type and filter out non-integral bit-fields that do not start and end on a byte boundary. gcc/testsuite/ * gnat.dg/opt101.adb: New test. * gnat.dg/opt101_pkg.ads: New helper.
This commit is contained in:
parent
77f27066c3
commit
180db383a9
@ -8428,20 +8428,26 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
|
||||
if (fieldsize == 0)
|
||||
continue;
|
||||
|
||||
/* Prepare to deal with integral bit-fields and filter out other
|
||||
bit-fields that do not start and end on a byte boundary. */
|
||||
if (DECL_BIT_FIELD (field))
|
||||
{
|
||||
if (!tree_fits_uhwi_p (DECL_FIELD_BIT_OFFSET (field)))
|
||||
return 0;
|
||||
fieldsize = TYPE_PRECISION (TREE_TYPE (field));
|
||||
bpos = tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field));
|
||||
if (bpos % BITS_PER_UNIT)
|
||||
bpos %= BITS_PER_UNIT;
|
||||
else
|
||||
bpos = 0;
|
||||
fieldsize += bpos;
|
||||
epos = fieldsize % BITS_PER_UNIT;
|
||||
fieldsize += BITS_PER_UNIT - 1;
|
||||
fieldsize /= BITS_PER_UNIT;
|
||||
if (INTEGRAL_TYPE_P (TREE_TYPE (field)))
|
||||
{
|
||||
bpos %= BITS_PER_UNIT;
|
||||
fieldsize = TYPE_PRECISION (TREE_TYPE (field)) + bpos;
|
||||
epos = fieldsize % BITS_PER_UNIT;
|
||||
fieldsize += BITS_PER_UNIT - 1;
|
||||
fieldsize /= BITS_PER_UNIT;
|
||||
}
|
||||
else if (bpos % BITS_PER_UNIT
|
||||
|| DECL_SIZE (field) == NULL_TREE
|
||||
|| !tree_fits_shwi_p (DECL_SIZE (field))
|
||||
|| tree_to_shwi (DECL_SIZE (field)) % BITS_PER_UNIT)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (off != -1 && pos + fieldsize <= off)
|
||||
@ -8450,7 +8456,8 @@ native_encode_initializer (tree init, unsigned char *ptr, int len,
|
||||
if (val == NULL_TREE)
|
||||
continue;
|
||||
|
||||
if (DECL_BIT_FIELD (field))
|
||||
if (DECL_BIT_FIELD (field)
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (field)))
|
||||
{
|
||||
/* FIXME: Handle PDP endian. */
|
||||
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
|
||||
|
23
gcc/testsuite/gnat.dg/opt101.adb
Normal file
23
gcc/testsuite/gnat.dg/opt101.adb
Normal file
@ -0,0 +1,23 @@
|
||||
-- { dg-do run }
|
||||
-- { dg-options "-O" }
|
||||
|
||||
pragma Optimize_Alignment (Space);
|
||||
|
||||
with Opt101_Pkg; use Opt101_Pkg;
|
||||
|
||||
procedure Opt101 is
|
||||
|
||||
C1 : Cont1;
|
||||
C2 : Cont2;
|
||||
|
||||
begin
|
||||
C1 := ((1234, 1, 2), 1, 2);
|
||||
if C1.R.I1 /= 1 or C1.I2 /= 2 then
|
||||
raise Program_Error;
|
||||
end if;
|
||||
|
||||
C2 := (1, (1234, 1, 2), 2);
|
||||
if C2.R.I1 /= 1 or C2.I2 /= 2 then
|
||||
raise Program_Error;
|
||||
end if;
|
||||
end;
|
26
gcc/testsuite/gnat.dg/opt101_pkg.ads
Normal file
26
gcc/testsuite/gnat.dg/opt101_pkg.ads
Normal file
@ -0,0 +1,26 @@
|
||||
package Opt101_Pkg is
|
||||
|
||||
type Int is mod 16;
|
||||
|
||||
type Rec is record
|
||||
S : Short_Integer;
|
||||
I1, I2 : Int;
|
||||
end record;
|
||||
pragma Pack (Rec);
|
||||
for Rec'Alignment use 4;
|
||||
|
||||
type Cont1 is record
|
||||
R : Rec;
|
||||
I1, I2 : Int;
|
||||
end record;
|
||||
pragma Pack (Cont1);
|
||||
|
||||
type Cont2 is record
|
||||
I1 : Int;
|
||||
R : Rec;
|
||||
I2 : Int;
|
||||
end record;
|
||||
pragma Pack (Cont2);
|
||||
pragma No_Component_Reordering (Cont2);
|
||||
|
||||
end Opt101_Pkg;
|
Loading…
x
Reference in New Issue
Block a user