gimple-fold: Fix another __builtin_clear_padding ICE
authorJakub Jelinek <jakub@redhat.com>
Fri, 27 Nov 2020 10:23:45 +0000 (11:23 +0100)
committerJakub Jelinek <jakub@redhat.com>
Fri, 27 Nov 2020 10:25:10 +0000 (11:25 +0100)
When playing with __builtin_bit_cast, I have noticed __builtin_clear_padding
ICE on the G class below.  The artificial field with D type has offset 0
and size 8 bytes, but the following artificial field with E type has offset
0 and size 0, so it triggers the asserts that we don't move current position
backwards.  Fixed by ignoring is_empty_type (TREE_TYPE (field)) fields, all
of their bits are padding which is what is added when skipping over to next
field anyway.

2020-11-27  Jakub Jelinek  <jakub@redhat.com>

PR libstdc++/88101
* gimple-fold.c (clear_padding_type): Ignore fields with is_empty_type
types.

* g++.dg/torture/builtin-clear-padding-3.C: New test.

gcc/gimple-fold.c
gcc/testsuite/g++.dg/torture/builtin-clear-padding-3.C [new file with mode: 0644]

index a821b649bf8f385e12f427acb941910620dd6dfd..1f3d80e288187301b37aafc8747c4b3daf2dc916 100644 (file)
@@ -4533,6 +4533,8 @@ clear_padding_type (clear_padding_struct *buf, tree type, HOST_WIDE_INT sz)
                                    "well defined padding bits for %qs",
                          field, "__builtin_clear_padding");
              }
+           else if (is_empty_type (TREE_TYPE (field)))
+             continue;
            else
              {
                HOST_WIDE_INT pos = int_byte_position (field);
diff --git a/gcc/testsuite/g++.dg/torture/builtin-clear-padding-3.C b/gcc/testsuite/g++.dg/torture/builtin-clear-padding-3.C
new file mode 100644 (file)
index 0000000..d528196
--- /dev/null
@@ -0,0 +1,24 @@
+/* PR libstdc++/88101 */
+
+struct D { int a; int : 24; int b : 8; };
+struct E {};
+struct F { char c, d, e; };
+struct G : public D, E, F { int f; } g1, g2;
+
+__attribute__((noipa)) void
+foo (G *g)
+{
+  g->a = -1; g->b = -1; g->c = -1; g->d = -1; g->e = -1; g->f = -1;
+}
+
+int
+main ()
+{
+  __builtin_memset (&g2, -1, sizeof (g2));
+  foo (&g1);
+  foo (&g2);
+  __builtin_clear_padding (&g2);
+  if (__builtin_memcmp (&g1, &g2, sizeof (g1)))
+    __builtin_abort ();
+  return 0;
+}