This resolves DR 1813 which says that for a class to be a standard-layout class, it may not have two (possibly indirect) base class subobjects of the same type. I was going to play DFS games but then I noticed we'd already set CLASSTYPE_REPEATED_BASE_P, making this significantly easier.
There are 3 related DRs which I opened PRs for: 91079 - [DR 1881] Standard-layout classes and unnamed bit-fields 91080 - [DR 1672] Layout compatibility with multiple empty bases 91081 - [DR 2120] Array as first non-static data member in standard-layout class Bootstrapped/regtested on x86_64-linux, ok for trunk? 2019-07-03 Marek Polacek <pola...@redhat.com> DR 1813 PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. * class.c (check_bases): Set CLASSTYPE_NON_STD_LAYOUT for a class if CLASSTYPE_REPEATED_BASE_P is true. * g++.dg/ext/is_std_layout3.C: New test. * g++.dg/ext/is_std_layout4.C: New test. diff --git gcc/cp/class.c gcc/cp/class.c index 73291b341fe..f77b7f4834b 100644 --- gcc/cp/class.c +++ gcc/cp/class.c @@ -1715,11 +1715,15 @@ check_bases (tree t, && (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (field), basetype))) CLASSTYPE_NON_STD_LAYOUT (t) = 1; + /* DR 1813: + ...has at most one base class subobject of any given type... */ + else if (CLASSTYPE_REPEATED_BASE_P (t)) + CLASSTYPE_NON_STD_LAYOUT (t) = 1; else /* ...either has no non-static data members in the most-derived class and at most one base class with non-static data members, or has no base classes with non-static data - members */ + members. FIXME This was reworded in DR 1813. */ for (basefield = TYPE_FIELDS (basetype); basefield; basefield = DECL_CHAIN (basefield)) if (TREE_CODE (basefield) == FIELD_DECL diff --git gcc/testsuite/g++.dg/ext/is_std_layout3.C gcc/testsuite/g++.dg/ext/is_std_layout3.C new file mode 100644 index 00000000000..b0555c8207b --- /dev/null +++ gcc/testsuite/g++.dg/ext/is_std_layout3.C @@ -0,0 +1,18 @@ +// DR 1813 +// PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. +// { dg-do compile { target c++11 } } + +struct B { int i; }; // standard-layout class +struct C : B { }; // standard-layout class +struct D : C { }; // standard-layout class +struct E : D { char : 4; }; // not a standard-layout class +static_assert( __is_standard_layout(B), "" ); +static_assert( __is_standard_layout(C), "" ); +static_assert( __is_standard_layout(D), "" ); +static_assert( ! __is_standard_layout(E), "" ); + +struct Q {}; +struct S : Q { }; +struct T : Q { }; +struct U : S, T { }; // not a standard-layout class +static_assert( ! __is_standard_layout(U), "" ); diff --git gcc/testsuite/g++.dg/ext/is_std_layout4.C gcc/testsuite/g++.dg/ext/is_std_layout4.C new file mode 100644 index 00000000000..09c0098120d --- /dev/null +++ gcc/testsuite/g++.dg/ext/is_std_layout4.C @@ -0,0 +1,11 @@ +// DR 1813 +// PR c++/83374 - __is_standard_layout wrong for a class with repeated bases. +// { dg-do compile { target c++11 } } + +struct R { }; +struct Q { }; +struct S : R { }; +struct T : Q { }; +struct U : S, T { }; +// No repeated base class subobjects. +static_assert(__is_standard_layout(U), "");