From a54333264a13c54b561bd55ba815f57f9bf33c91 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sat, 20 Jul 2013 01:06:31 +0000 Subject: [PATCH] Fix bug in computing POD-for-layout. A class with a field of non-POD-for-layout type is not POD-for-layout. This computation should not depend on whether the field is of POD type in the language sense. Fixes PR16537. Patch by Josh Magee. llvm-svn: 186741 --- clang/docs/ReleaseNotes.rst | 4 + clang/lib/AST/DeclCXX.cpp | 2 +- clang/test/SemaCXX/class-layout.cpp | 469 +++++++++++++++++++++++++++++++++++- 3 files changed, 473 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d375547..601f566 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -74,6 +74,10 @@ C11 Feature Support C++ Language Changes in Clang ----------------------------- +- Fixed an ABI regression, introduced in Clang 3.2, which affected + member offsets for classes inheriting from certain classes with tail padding. + See PR16537. + - ... C++11 Feature Support diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index dacb867..ceebbe0 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -662,7 +662,7 @@ void CXXRecordDecl::addedMember(Decl *D) { if (!Context.getLangOpts().ObjCAutoRefCount || T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) setHasObjectMember(true); - } else if (!T.isPODType(Context)) + } else if (!T.isCXX98PODType(Context)) data().PlainOldData = false; if (T->isReferenceType()) { diff --git a/clang/test/SemaCXX/class-layout.cpp b/clang/test/SemaCXX/class-layout.cpp index f2ff9fc..64c8ceb 100644 --- a/clang/test/SemaCXX/class-layout.cpp +++ b/clang/test/SemaCXX/class-layout.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 // expected-no-diagnostics #define SA(n, p) int a##n[(p) ? 1 : -1] @@ -103,3 +104,469 @@ struct H { G g; }; SA(0, sizeof(H) == 24); } + +namespace PR16537 { +namespace test1 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only { + char may_go_into_tail_padding; + }; + + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test2 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11 __attribute__((aligned(16))); + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only { + char may_go_into_tail_padding; + }; + + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test3 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct second_base { + char foo; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base { + + }; + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test4 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct second_base { + char foo; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base { + char may_go_into_tail_padding; + }; + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test5 { + struct pod_in_11_only { + private: + long long x; + }; + + struct pod_in_11_only2 { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct second_base { + pod_in_11_only2 two; + char foo; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base { + char may_go_into_tail_padding; + }; + SA(0, sizeof(might_use_tail_padding) == 32); +} + +namespace test6 { + struct pod_in_11_only { + private: + long long x; + }; + + struct pod_in_11_only2 { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct second_base { + pod_in_11_only2 two; + char foo; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only, public second_base { + char may_go_into_tail_padding; + }; + SA(0, sizeof(might_use_tail_padding) == 32); +} + +namespace test7 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + pod_in_11_only pod12; + char tail_padding; + }; + + struct might_use_tail_padding : public tail_padded_pod_in_11_only { + char may_go_into_tail_padding; + }; + + SA(0, sizeof(might_use_tail_padding) == 24); +} + +namespace test8 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct another_layer { + tail_padded_pod_in_11_only pod; + char padding; + }; + + struct might_use_tail_padding : public another_layer { + char may_go_into_tail_padding; + }; + + SA(0, sizeof(might_use_tail_padding) == 24); +} + +namespace test9 { + struct pod_in_11_only { + private: + long long x; + }; + + struct tail_padded_pod_in_11_only { + pod_in_11_only pod11; + char tail_padding; + }; + + struct another_layer : tail_padded_pod_in_11_only { + }; + + struct might_use_tail_padding : public another_layer { + char may_go_into_tail_padding; + }; + + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test10 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct B { + char b; + }; + + struct C { + pod_in_11_only c; + char cpad; + }; + + struct D { + char d; + }; + + struct might_use_tail_padding : public A, public B, public C, public D { + }; + + SA(0, sizeof(might_use_tail_padding) == 32); +} + +namespace test11 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct B { + char b_pre; + pod_in_11_only b; + char bpad; + }; + + struct C { + char c_pre; + pod_in_11_only c; + char cpad; + }; + + struct D { + char d_pre; + pod_in_11_only d; + char dpad; + }; + + struct might_use_tail_padding : public A, public B, public C, public D { + char m; + }; + + SA(0, sizeof(might_use_tail_padding) == 88); +} + +namespace test12 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a __attribute__((aligned(128))); + }; + + struct B { + char bpad; + }; + + struct C { + char cpad; + }; + + struct D { + char dpad; + }; + + struct might_use_tail_padding : public A, public B, public C, public D { + char m; + }; + SA(0, sizeof(might_use_tail_padding) == 128); +} + +namespace test13 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct B { + }; + + struct C { + char c_pre; + pod_in_11_only c; + char cpad; + }; + + struct D { + }; + + struct might_use_tail_padding : public A, public B, public C, public D { + char m; + }; + SA(0, sizeof(might_use_tail_padding) == 40); +} + +namespace test14 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct might_use_tail_padding : public A { + struct { + int : 0; + } x; + }; + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test15 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct might_use_tail_padding : public A { + struct { + char a:1; + char b:2; + char c:2; + char d:2; + char e:1; + } x; + }; + SA(0, sizeof(might_use_tail_padding) == 16); +} + +namespace test16 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct B { + char bpod; + pod_in_11_only b; + char bpad; + }; + + struct C : public A, public B { + }; + + struct D : public C { + }; + + struct might_use_tail_padding : public D { + char m; + }; + SA(0, sizeof(might_use_tail_padding) == 40); +} + +namespace test17 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a __attribute__((aligned(512))); + }; + + struct B { + char bpad; + pod_in_11_only foo; + char btail; + }; + + struct C { + char cpad; + }; + + struct D { + char dpad; + }; + + struct might_use_tail_padding : public A, public B, public C, public D { + char a; + }; + SA(0, sizeof(might_use_tail_padding) == 512); +} + +namespace test18 { + struct pod_in_11_only { + private: + long long x; + }; + + struct A { + pod_in_11_only a; + char apad; + }; + + struct B { + char bpod; + pod_in_11_only b; + char bpad; + }; + + struct A1 { + pod_in_11_only a; + char apad; + }; + + struct B1 { + char bpod; + pod_in_11_only b; + char bpad; + }; + + struct C : public A, public B { + }; + + struct D : public A1, public B1 { + }; + + struct E : public D, public C { + }; + + struct F : public E { + }; + + struct might_use_tail_padding : public F { + char m; + }; + SA(0, sizeof(might_use_tail_padding) == 80); +} +} // namespace PR16537 -- 2.7.4