Base fields for empty bases appear in initialization order, which may not be
the same as layout order.  If they also show up in a CONSTRUCTOR in that
order, output_constructor_regular_field aborts because it understandably
doesn't want to go backwards.  I also considered making o_c_r_f more
tolerant of the case where the out-of-order field has fieldsize 0, and so no
actual data needs to be emitted, but we might as well avoid adding an
element to the CONSTRUCTOR in the first place.

Tested x86_64-pc-linux-gnu, applying to trunk.

        * typeck2.c (process_init_constructor_record): Skip trivial
        initialization of an empty base.
---
 gcc/cp/typeck2.c                        | 7 +++++++
 gcc/testsuite/g++.dg/cpp1z/aggr-base7.C | 8 ++++++++
 gcc/cp/ChangeLog                        | 6 ++++++
 3 files changed, 21 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/aggr-base7.C

diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index b265ea05741..456c4fcb748 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1627,6 +1627,13 @@ process_init_constructor_record (tree type, tree init, 
int nested, int flags,
            }
        }
 
+      if (DECL_SIZE (field) && integer_zerop (DECL_SIZE (field))
+         && !TREE_SIDE_EFFECTS (next))
+       /* Don't add trivial initialization of an empty base/field to the
+          constructor, as they might not be ordered the way the back-end
+          expects.  */
+       continue;
+
       /* If this is a bitfield, now convert to the lowered type.  */
       if (type != TREE_TYPE (field))
        next = cp_convert_and_check (TREE_TYPE (field), next, complain);
diff --git a/gcc/testsuite/g++.dg/cpp1z/aggr-base7.C 
b/gcc/testsuite/g++.dg/cpp1z/aggr-base7.C
new file mode 100644
index 00000000000..bc1793e79ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/aggr-base7.C
@@ -0,0 +1,8 @@
+// PR c++/88690
+// { dg-do compile { target c++11 } }
+
+struct A { int a = 1; };
+struct B { int b = 0; };
+struct C { C() = default; C (const C&) = delete; };
+struct D : public B, public C {};
+struct E : A { D f; } g{};
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3009b58a3b4..89a1bcac80b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2019-02-20  Jason Merrill  <ja...@redhat.com>
+
+       PR c++/88690 - C++17 ICE with empty base in aggregate.
+       * typeck2.c (process_init_constructor_record): Skip trivial
+       initialization of an empty base.
+
 2019-02-21  Richard Biener  <rguent...@suse.de>
 
        PR middle-end/89392

base-commit: f867b437c79cf560a55b778b947983bb08df158b
-- 
2.20.1

Reply via email to