blob: 7dca12190584685797d0dd3f91b39715b85b918b [file] [log] [blame]
Reid Kleckner84e9ab42013-03-28 20:02:56 +00001// RUN: %clang_cc1 -std=c++11 -cxx-abi microsoft -fms-compatibility -fsyntax-only -triple=i386-pc-win32 -verify %s
2// RUN: %clang_cc1 -std=c++11 -cxx-abi microsoft -fms-compatibility -fsyntax-only -triple=x86_64-pc-win32 -verify %s
3//
4// This file should also give no diagnostics when run through cl.exe from MSVS
5// 2012, which supports C++11 and static_assert. It should pass for both 64-bit
6// and 32-bit x86.
7//
8// expected-no-diagnostics
Joao Matos679fc932012-09-04 17:18:12 +00009
Reid Kleckner84e9ab42013-03-28 20:02:56 +000010// Test the size of various member pointer combinations:
11// - complete and incomplete
12// - single, multiple, and virtual inheritance (and unspecified for incomplete)
13// - data and function pointers
14// - templated with declared specializations with annotations
15// - template that can be instantiated
Charles Davisd18f9f92010-08-16 04:01:50 +000016
Reid Kleckner84e9ab42013-03-28 20:02:56 +000017// http://llvm.org/PR12070
18struct Foo {
19 typedef int Foo::*FooInt;
20 int f;
21};
Charles Davisf231df32010-08-16 05:30:44 +000022
Reid Kleckner84e9ab42013-03-28 20:02:56 +000023enum {
24 kSingleDataSize = 1 * sizeof(int),
25 kSingleFunctionSize = 1 * sizeof(void *),
26 kMultipleDataSize = 1 * sizeof(int),
27 kMultipleFunctionSize = 2 * sizeof(void *),
28 kVirtualDataSize = 2 * sizeof(int),
29 kVirtualFunctionSize = 2 * sizeof(int) + 1 * sizeof(void *),
30 // Unspecified is weird, it's 1 more slot than virtual.
31 kUnspecifiedDataSize = kVirtualDataSize + 1 * sizeof(int),
32 kUnspecifiedFunctionSize = kVirtualFunctionSize + 1 * sizeof(void *),
33};
34
35// incomplete types
36class __single_inheritance IncSingle;
37class __multiple_inheritance IncMultiple;
38class __virtual_inheritance IncVirtual;
39static_assert(sizeof(int IncSingle::*) == kSingleDataSize, "");
40static_assert(sizeof(int IncMultiple::*) == kMultipleDataSize, "");
41static_assert(sizeof(int IncVirtual::*) == kVirtualDataSize, "");
42static_assert(sizeof(void (IncSingle::*)()) == kSingleFunctionSize, "");
43static_assert(sizeof(void (IncMultiple::*)()) == kMultipleFunctionSize, "");
44static_assert(sizeof(void (IncVirtual::*)()) == kVirtualFunctionSize, "");
45
46// An incomplete type with an unspecified inheritance model seems to take one
47// more slot than virtual. It's not clear what it's used for yet.
48class IncUnspecified;
49static_assert(sizeof(int IncUnspecified::*) == kUnspecifiedDataSize, "");
50static_assert(sizeof(void (IncUnspecified::*)()) == kUnspecifiedFunctionSize, "");
51
52// complete types
53struct B1 { };
54struct B2 { };
55struct Single { };
56struct Multiple : B1, B2 { };
57struct Virtual : virtual B1 { };
58static_assert(sizeof(int Single::*) == kSingleDataSize, "");
59static_assert(sizeof(int Multiple::*) == kMultipleDataSize, "");
60static_assert(sizeof(int Virtual::*) == kVirtualDataSize, "");
61static_assert(sizeof(void (Single::*)()) == kSingleFunctionSize, "");
62static_assert(sizeof(void (Multiple::*)()) == kMultipleFunctionSize, "");
63static_assert(sizeof(void (Virtual::*)()) == kVirtualFunctionSize, "");
64
65// Test both declared and defined templates.
66template <typename T> class X;
67template <> class __single_inheritance X<IncSingle>;
68template <> class __multiple_inheritance X<IncMultiple>;
69template <> class __virtual_inheritance X<IncVirtual>;
70// Don't declare X<IncUnspecified>.
71static_assert(sizeof(int X<IncSingle>::*) == kSingleDataSize, "");
72static_assert(sizeof(int X<IncMultiple>::*) == kMultipleDataSize, "");
73static_assert(sizeof(int X<IncVirtual>::*) == kVirtualDataSize, "");
74static_assert(sizeof(int X<IncUnspecified>::*) == kUnspecifiedDataSize, "");
75static_assert(sizeof(void (X<IncSingle>::*)()) == kSingleFunctionSize, "");
76static_assert(sizeof(void (X<IncMultiple>::*)()) == kMultipleFunctionSize, "");
77static_assert(sizeof(void (X<IncVirtual>::*)()) == kVirtualFunctionSize, "");
78static_assert(sizeof(void (X<IncUnspecified>::*)()) == kUnspecifiedFunctionSize, "");
79
80template <typename T>
81struct Y : T { };
82static_assert(sizeof(int Y<Single>::*) == kSingleDataSize, "");
83static_assert(sizeof(int Y<Multiple>::*) == kMultipleDataSize, "");
84static_assert(sizeof(int Y<Virtual>::*) == kVirtualDataSize, "");
85static_assert(sizeof(void (Y<Single>::*)()) == kSingleFunctionSize, "");
86static_assert(sizeof(void (Y<Multiple>::*)()) == kMultipleFunctionSize, "");
87static_assert(sizeof(void (Y<Virtual>::*)()) == kVirtualFunctionSize, "");
88
89struct A { int x; void bar(); };
90struct B : A { virtual void foo(); };
91static_assert(sizeof(int B::*) == kSingleDataSize, "");
92// A non-primary base class uses the multiple inheritance model for member
93// pointers.
94static_assert(sizeof(void (B::*)()) == kMultipleFunctionSize, "");
95
96struct AA { int x; virtual void foo(); };
97struct BB : AA { void bar(); };
98struct CC : BB { virtual void baz(); };
99static_assert(sizeof(void (CC::*)()) == kSingleFunctionSize, "");
100
101// We start out unspecified.
102struct ForwardDecl1;
103struct ForwardDecl2;
104
105// Re-declare to force us to iterate decls when adding attributes.
106struct ForwardDecl1;
107struct ForwardDecl2;
108
109typedef int ForwardDecl1::*MemPtr1;
110typedef int ForwardDecl2::*MemPtr2;
111MemPtr1 variable_forces_sizing;
112
113struct ForwardDecl1 : B {
114 virtual void foo();
115};
116struct ForwardDecl2 : B {
117 virtual void foo();
118};
119
120static_assert(sizeof(variable_forces_sizing) == kUnspecifiedDataSize, "");
121static_assert(sizeof(MemPtr1) == kUnspecifiedDataSize, "");
122// FIXME: Clang fails this assert because it locks in the inheritance model at
123// the point of the typedef instead of the first usage, while MSVC does not.
124//static_assert(sizeof(MemPtr2) == kSingleDataSize, "");
125
126struct MemPtrInBody {
127 typedef int MemPtrInBody::*MemPtr;
128 int a;
129 operator MemPtr() const {
130 return a ? &MemPtrInBody::a : 0;
131 }
132};
133
134static_assert(sizeof(MemPtrInBody::MemPtr) == kSingleDataSize, "");
Reid Klecknere93e2552013-03-28 23:11:29 +0000135
136// Passing a member pointer through a template should get the right size.
137template<typename T>
138struct SingleTemplate;
139template<typename T>
140struct SingleTemplate<void (T::*)(void)> {
141 static_assert(sizeof(int T::*) == kSingleDataSize, "");
142 static_assert(sizeof(void (T::*)()) == kSingleFunctionSize, "");
143};
144
145template<typename T>
146struct UnspecTemplate;
147template<typename T>
148struct UnspecTemplate<void (T::*)(void)> {
149 static_assert(sizeof(int T::*) == kUnspecifiedDataSize, "");
150 static_assert(sizeof(void (T::*)()) == kUnspecifiedFunctionSize, "");
151};
152
153struct NewUnspecified;
154SingleTemplate<void (IncSingle::*)()> tmpl_single;
155UnspecTemplate<void (NewUnspecified::*)()> tmpl_unspec;
156
157struct NewUnspecified { };
158
159static_assert(sizeof(void (NewUnspecified::*)()) == kUnspecifiedFunctionSize, "");
160
161template <typename T>
162struct MemPtrInTemplate {
163 // We can't require that the template arg be complete until we're
164 // instantiated.
165 int T::*data_ptr;
166 void (T::*func_ptr)();
167};