================ @@ -488,3 +488,89 @@ static_assert(__is_trivially_copyable(S12)); // expected-note@-1 {{'S12' is not trivially copyable}} \ // expected-note@#tc-S12 {{'S12' defined here}} } + +namespace standard_layout_tests { +struct WithVirtual { // #sl-Virtual + virtual void foo(); // #sl-Virtual-Foo +}; +static_assert(__is_standard_layout(WithVirtual)); +// expected-error@-1 {{static assertion failed due to requirement '__is_standard_layout(standard_layout_tests::WithVirtual)'}} \ +// expected-note@-1 {{'WithVirtual' is not standard-layout}} \ +// expected-note@-1 {{because it has a virtual function}} \ +// expected-note@#sl-Virtual-Foo {{'foo' defined here}} \ +// expected-note@#sl-Virtual {{'WithVirtual' defined here}} + +struct MixedAccess { // #sl-Mixed +public: + int a; // #sl-MixedF1 +private: + int b; // #sl-MixedF2 +}; +static_assert(__is_standard_layout(MixedAccess)); +// expected-error@-1 {{static assertion failed due to requirement '__is_standard_layout(standard_layout_tests::MixedAccess)'}} \ +// expected-note@-1 {{'MixedAccess' is not standard-layout}} \ +// expected-note@-1 {{because it has mixed access specifiers}} \ +// expected-note@#sl-MixedF1 {{'a' defined here}} +// expected-note@#sl-MixedF2 {{field 'b' has a different access specifier than field 'a'}} +// expected-note@#sl-Mixed {{'MixedAccess' defined here}} + +struct VirtualBase { virtual ~VirtualBase(); }; // #sl-VirtualBase +struct VB : virtual VirtualBase {}; // #sl-VB +static_assert(__is_standard_layout(VB)); +// expected-error@-1 {{static assertion failed due to requirement '__is_standard_layout(standard_layout_tests::VB)'}} \ +// expected-note@-1 {{'VB' is not standard-layout}} \ +// expected-note@-1 {{because it has a virtual base 'VirtualBase'}} \ +// expected-note@-1 {{because it has a non-standard-layout base 'VirtualBase'}} \ +// expected-note@-1 {{because it has a virtual function}} +// expected-note@#sl-VB {{'VB' defined here}} +// expected-note@#sl-VB {{'~VB' defined here}} + +union U { // #sl-U +public: + int x; // #sl-UF1 +private: + int y; // #sl-UF2 +}; +static_assert(__is_standard_layout(U)); +// expected-error@-1 {{static assertion failed due to requirement '__is_standard_layout(standard_layout_tests::U)'}} \ +// expected-note@-1 {{'U' is not standard-layout}} \ +// expected-note@-1 {{because it has mixed access specifiers}} +// expected-note@#sl-UF1 {{'x' defined here}} +// expected-note@#sl-UF2 {{field 'y' has a different access specifier than field 'x'}} +// expected-note@#sl-U {{'U' defined here}} + +// Single base class is OK +struct BaseClass{ int a; }; // #sl-BaseClass +struct DerivedOK : BaseClass {}; // #sl-DerivedOK +static_assert(__is_standard_layout(DerivedOK)); + +// Primitive types should be standard layout +static_assert(__is_standard_layout(int)); // #sl-Int +static_assert(__is_standard_layout(float)); // #sl-Float + +// Multi-level inheritance: Non-standard layout +struct Base1 { int a; }; // #sl-Base1 +struct Base2 { int b; }; // #sl-Base2 +struct DerivedClass : Base1, Base2 {}; // #sl-DerivedClass +static_assert(__is_standard_layout(DerivedClass)); +// expected-error@-1 {{static assertion failed due to requirement '__is_standard_layout(standard_layout_tests::DerivedClass)'}} \ +// expected-note@-1 {{'DerivedClass' is not standard-layout}} \ +// expected-note@-1 {{because it has multiple base classes with data members}} \ +// expected-note@#sl-DerivedClass {{'DerivedClass' defined here}} + +// Inheritance hierarchy with multiple classes having data members +struct BaseA { int a; }; // #sl-BaseA +struct BaseB : BaseA {}; // inherits BaseA, has no new members +struct BaseC: BaseB { int c; }; // #sl-BaseC +static_assert(__is_standard_layout(BaseC)); +// expected-error@-1 {{static assertion failed due to requirement '__is_standard_layout(standard_layout_tests::BaseC)'}} \ +// expected-note@-1 {{'BaseC' is not standard-layout}} \ +// expected-note@-1 {{because it has an indirect base 'BaseA' with data members}} \ +// expected-note@#sl-BaseC {{'BaseC' defined here}} \ +// Multiple direct base classes with no data members --> standard layout +struct BaseX {}; // #sl-BaseX +struct BaseY {}; // #sl-BaseY +struct MultiBase : BaseX, BaseY {}; // #sl-MultiBase ---------------- AaronBallman wrote:
Some other test cases to consider: ``` struct A { int x; }; struct B : A { }; struct C : B { int y; }; // Indirect bases with multiple members struct D { union { int a; float b; }; }; // Standard layout struct E : D { int x; }; // Not standard layout struct F : D { int : 0; }; // Standard layout struct Empty {}; struct G { Empty a, b; }; // Standard layout struct H { Empty a; int x; }; // Standard layout struct I { Empty a; int : 0; int x; }; // Standard layout ``` Additionally, we should care about `[[no_unique_address]]` (and the msvc variant of it as well). https://github.com/llvm/llvm-project/pull/144161 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits