aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2023-05-23 10:15:35 +0200
committerEric Botcazou <ebotcazou@adacore.com>2023-05-23 10:17:13 +0200
commit50143b85bd90a2e06c0dd192a966574a3279c463 (patch)
tree769c6056f19f54b5de7993a5af034e8fe943ffe6
parent61285c4805bc4fff417e9eb034f91a4d0dc2d335 (diff)
downloadgcc-50143b85bd90a2e06c0dd192a966574a3279c463.zip
gcc-50143b85bd90a2e06c0dd192a966574a3279c463.tar.gz
gcc-50143b85bd90a2e06c0dd192a966574a3279c463.tar.bz2
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.
-rw-r--r--gcc/fold-const.cc27
-rw-r--r--gcc/testsuite/gnat.dg/opt101.adb23
-rw-r--r--gcc/testsuite/gnat.dg/opt101_pkg.ads26
3 files changed, 66 insertions, 10 deletions
diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 25466e9..5752150 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -8360,20 +8360,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)
@@ -8382,7 +8388,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)
diff --git a/gcc/testsuite/gnat.dg/opt101.adb b/gcc/testsuite/gnat.dg/opt101.adb
new file mode 100644
index 0000000..68773bb
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt101.adb
@@ -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;
diff --git a/gcc/testsuite/gnat.dg/opt101_pkg.ads b/gcc/testsuite/gnat.dg/opt101_pkg.ads
new file mode 100644
index 0000000..0c843df
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt101_pkg.ads
@@ -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;