teak-llvm/clang/test/SemaCXX/class-layout.cpp
Richard Smith 4ae767ba3d PR37275 packed attribute should not apply to base classes
Clang incorrectly applied the packed attribute to base classes. Per GCC's
documentation and as can be observed from its behavior, packed only applies to
members, not base classes.

This change is conditioned behind -fclang-abi-compat so that an ABI break can
be avoided by users if desired.

Differential Revision: https://reviews.llvm.org/D46218

llvm-svn: 331136
2018-04-29 04:55:46 +00:00

607 lines
10 KiB
C++

// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base
// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6
// expected-no-diagnostics
#define SA(n, p) int a##n[(p) ? 1 : -1]
struct A {
int a;
char b;
};
SA(0, sizeof(A) == 8);
struct B : A {
char c;
};
SA(1, sizeof(B) == 12);
struct C {
// Make fields private so C won't be a POD type.
private:
int a;
char b;
};
SA(2, sizeof(C) == 8);
struct D : C {
char c;
};
SA(3, sizeof(D) == 8);
struct __attribute__((packed)) E {
char b;
int a;
};
SA(4, sizeof(E) == 5);
struct __attribute__((packed)) F : E {
char d;
};
SA(5, sizeof(F) == 6);
struct G { G(); };
struct H : G { };
SA(6, sizeof(H) == 1);
struct I {
char b;
int a;
} __attribute__((packed));
SA(6_1, sizeof(I) == 5);
// PR5580
namespace PR5580 {
class A { bool iv0 : 1; };
SA(7, sizeof(A) == 1);
class B : A { bool iv0 : 1; };
SA(8, sizeof(B) == 2);
struct C { bool iv0 : 1; };
SA(9, sizeof(C) == 1);
struct D : C { bool iv0 : 1; };
SA(10, sizeof(D) == 2);
}
namespace Test1 {
// Test that we don't assert on this hierarchy.
struct A { };
struct B : A { virtual void b(); };
class C : virtual A { int c; };
struct D : virtual B { };
struct E : C, virtual D { };
class F : virtual E { };
struct G : virtual E, F { };
SA(0, sizeof(G) == 24);
}
namespace Test2 {
// Test that this somewhat complex class structure is laid out correctly.
struct A { };
struct B : A { virtual void b(); };
struct C : virtual B { };
struct D : virtual A { };
struct E : virtual B, D { };
struct F : E, virtual C { };
struct G : virtual F, A { };
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
namespace PR37275 {
struct X { char c; };
struct A { int n; };
_Static_assert(_Alignof(A) == _Alignof(int), "");
// __attribute__((packed)) does not apply to base classes.
struct __attribute__((packed)) B : X, A {};
#if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 6
_Static_assert(_Alignof(B) == 1, "");
_Static_assert(__builtin_offsetof(B, n) == 1, "");
#else
_Static_assert(_Alignof(B) == _Alignof(int), "");
_Static_assert(__builtin_offsetof(B, n) == 4, "");
#endif
// #pragma pack does, though.
#pragma pack(push, 2)
struct C : X, A {};
_Static_assert(_Alignof(C) == 2, "");
_Static_assert(__builtin_offsetof(C, n) == 2, "");
struct __attribute__((packed)) D : X, A {};
#if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 6
_Static_assert(_Alignof(D) == 1, "");
_Static_assert(__builtin_offsetof(D, n) == 1, "");
#else
_Static_assert(_Alignof(D) == 2, "");
_Static_assert(__builtin_offsetof(D, n) == 2, "");
#endif
#pragma pack(pop)
}