1 | // clang-format off |
2 | // REQUIRES: lld, x86 |
3 | |
4 | // Test various interesting cases for AST reconstruction. |
5 | // RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -c /Fo%t.obj -- %s |
6 | // RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb |
7 | // RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \ |
8 | // RUN: %p/Inputs/ast-types.lldbinit 2>&1 | FileCheck %s |
9 | |
10 | // Test trivial versions of each tag type. |
11 | class TrivialC {}; |
12 | struct TrivialS {}; |
13 | union TrivialU {}; |
14 | enum TrivialE {TE_A}; |
15 | |
16 | // Test reconstruction of DeclContext hierarchies. |
17 | namespace A { |
18 | namespace B { |
19 | template<typename T> |
20 | struct C { |
21 | T ABCMember; |
22 | }; |
23 | |
24 | // Let's try a template specialization with a different implementation |
25 | template<> |
26 | struct C<void> { |
27 | void *ABCSpecializationMember; |
28 | }; |
29 | } |
30 | |
31 | // Let's make sure we can distinguish classes and namespaces. Also let's try |
32 | // a non-type template parameter. |
33 | template<int N> |
34 | struct C { |
35 | class D { |
36 | int ACDMember = 0; |
37 | C<N - 1> *CPtr = nullptr; |
38 | }; |
39 | }; |
40 | |
41 | struct D { |
42 | // Let's make a nested class with the same name as another nested class |
43 | // elsewhere, and confirm that they appear in the right DeclContexts in |
44 | // the AST. |
45 | struct E { |
46 | int ADDMember; |
47 | }; |
48 | }; |
49 | } |
50 | |
51 | |
52 | // Let's try an anonymous namespace. |
53 | namespace { |
54 | template<typename T> |
55 | struct Anonymous { |
56 | int AnonymousMember; |
57 | // And a nested class within an anonymous namespace |
58 | struct D { |
59 | int AnonymousDMember; |
60 | }; |
61 | }; |
62 | } |
63 | |
64 | TrivialC TC; |
65 | TrivialS TS; |
66 | TrivialU TU; |
67 | TrivialE TE; |
68 | |
69 | A::B::C<int> ABCInt; |
70 | A::B::C<float> ABCFloat; |
71 | A::B::C<void> ABCVoid; |
72 | |
73 | A::C<0> AC0; |
74 | A::C<-1> ACNeg1; |
75 | |
76 | // FIXME: The type `D` is located now at the level of the translation unit. |
77 | // FIXME: Should be located in the namespace `A`, in the struct `C<1>`. |
78 | A::C<1>::D AC1D; |
79 | |
80 | A::C<0>::D AC0D; |
81 | A::C<-1>::D ACNeg1D; |
82 | A::D AD; |
83 | A::D::E ADE; |
84 | |
85 | Anonymous<int> AnonInt; |
86 | Anonymous<A::B::C<void>> AnonABCVoid; |
87 | Anonymous<A::B::C<void>>::D AnonABCVoidD; |
88 | |
89 | // The following tests that MSInheritanceAttr are set for record decls. |
90 | class SI { int si; }; |
91 | struct SI2 { int si2; }; |
92 | class MI : SI, SI2 { int mi; }; |
93 | class MI2 : MI { int mi2; }; |
94 | class VI : virtual MI { int vi; }; |
95 | class VI2 : virtual SI, virtual SI2 { int vi; }; |
96 | class/* __unspecified_inheritance*/ UI; |
97 | |
98 | typedef void (SI::*SITYPE)(); |
99 | typedef void (MI::*MITYPE)(); |
100 | typedef void (MI2::*MI2TYPE)(); |
101 | typedef void (VI::*VITYPE)(); |
102 | typedef void (VI2::*VI2TYPE)(); |
103 | typedef void (UI::*UITYPE)(); |
104 | SITYPE mp1 = nullptr; |
105 | MITYPE mp2 = nullptr; |
106 | MI2TYPE mp3 = nullptr; |
107 | VITYPE mp4 = nullptr; |
108 | VI2TYPE mp5 = nullptr; |
109 | UITYPE mp6 = nullptr; |
110 | MITYPE *mp7 = nullptr; |
111 | VI2TYPE *mp8 = nullptr; |
112 | int SI::*mp9 = nullptr; |
113 | |
114 | // FIXME: Enum size isn't being correctly determined. |
115 | // FIXME: Can't read memory for variable values. |
116 | |
117 | // CHECK: (TrivialC) TC = {} |
118 | // CHECK: (TrivialS) TS = {} |
119 | // CHECK: (TrivialU) TU = {} |
120 | // CHECK: (TrivialE) TE = TE_A |
121 | // CHECK: (A::B::C<int>) ABCInt = (ABCMember = 0) |
122 | // CHECK: (A::B::C<float>) ABCFloat = (ABCMember = 0) |
123 | // CHECK: (A::B::C<void>) ABCVoid = (ABCSpecializationMember = 0x{{0+}}) |
124 | // CHECK: (A::C<0>) AC0 = {} |
125 | // CHECK: (A::C<-1>) ACNeg1 = {} |
126 | // CHECK: (A::C<1>::D) AC1D = (ACDMember = 0, CPtr = 0x{{0+}}) |
127 | // CHECK: (A::C<0>::D) AC0D = (ACDMember = 0, CPtr = 0x{{0+}}) |
128 | // CHECK: (A::C<-1>::D) ACNeg1D = (ACDMember = 0, CPtr = 0x{{0+}}) |
129 | // CHECK: (A::D) AD = {} |
130 | // CHECK: (A::D::E) ADE = (ADDMember = 0) |
131 | // CHECK: (Anonymous<int>) AnonInt = (AnonymousMember = 0) |
132 | // CHECK: (Anonymous<A::B::C<void>>) AnonABCVoid = (AnonymousMember = 0) |
133 | // CHECK: (Anonymous<A::B::C<void>>::D) AnonABCVoidD = (AnonymousDMember = 0) |
134 | // CHECK: (void (SI::*)()) mp1 = 0x0000000000000000 |
135 | // CHECK: (void (MI::*)()) mp2 = 0x0000000000000000 |
136 | // CHECK: (void (MI2::*)()) mp3 = 0x0000000000000000 |
137 | // CHECK: (void (VI::*)()) mp4 = 0x0000000000000000 |
138 | // CHECK: (void (VI2::*)()) mp5 = 0x0000000000000000 |
139 | // CHECK: (void (UI::*)()) mp6 = 0x0000000000000000 |
140 | // CHECK: (void (MI::**)()) mp7 = 0x0000000000000000 |
141 | // CHECK: (void (VI2::**)()) mp8 = 0x0000000000000000 |
142 | // CHECK: (int SI::*) mp9 = 0xffffffff |
143 | // CHECK: Dumping clang ast for 1 modules. |
144 | // CHECK: TranslationUnitDecl {{.*}} |
145 | // CHECK: |-CXXRecordDecl {{.*}} class TrivialC definition |
146 | // CHECK: |-CXXRecordDecl {{.*}} struct TrivialS definition |
147 | // CHECK: |-CXXRecordDecl {{.*}} union TrivialU definition |
148 | // CHECK: |-EnumDecl {{.*}} TrivialE |
149 | // CHECK: | `-EnumConstantDecl {{.*}} TE_A 'TrivialE' |
150 | // CHECK: |-NamespaceDecl {{.*}} A |
151 | // CHECK: | |-NamespaceDecl {{.*}} B |
152 | // CHECK: | | |-CXXRecordDecl {{.*}} struct C<int> definition |
153 | // CHECK: | | | `-FieldDecl {{.*}} ABCMember 'int' |
154 | // CHECK: | | |-CXXRecordDecl {{.*}} struct C<float> definition |
155 | // CHECK: | | | `-FieldDecl {{.*}} ABCMember 'float' |
156 | // CHECK: | | `-CXXRecordDecl {{.*}} struct C<void> definition |
157 | // CHECK: | | `-FieldDecl {{.*}} ABCSpecializationMember 'void *' |
158 | // FIXME: | |-CXXRecordDecl {{.*}} struct C<1> definition |
159 | // FIXME: | | `-CXXRecordDecl {{.*}} class D definition |
160 | // FIXME: | | |-FieldDecl {{.*}} ACDMember 'int' |
161 | // FIXME: | | `-FieldDecl {{.*}} CPtr 'A::C<1> *' |
162 | // CHECK: | |-CXXRecordDecl {{.*}} struct C<0> definition |
163 | // CHECK: | | `-CXXRecordDecl {{.*}} class D definition |
164 | // CHECK: | | |-FieldDecl {{.*}} ACDMember 'int' |
165 | // CHECK: | | `-FieldDecl {{.*}} CPtr 'A::C<-1> *' |
166 | // CHECK: | |-CXXRecordDecl {{.*}} struct C<-1> definition |
167 | // CHECK: | | `-CXXRecordDecl {{.*}} class D definition |
168 | // CHECK: | | |-FieldDecl {{.*}} ACDMember 'int' |
169 | // CHECK: | | `-FieldDecl {{.*}} CPtr 'A::C<-2> *' |
170 | // CHECK: | |-CXXRecordDecl {{.*}} struct C<-2> |
171 | // CHECK: | `-CXXRecordDecl {{.*}} struct D definition |
172 | // CHECK: | `-CXXRecordDecl {{.*}} struct E definition |
173 | // CHECK: | `-FieldDecl {{.*}} ADDMember 'int' |
174 | // CHECK: |-NamespaceDecl |
175 | // CHECK: | |-CXXRecordDecl {{.*}} struct Anonymous<int> definition |
176 | // CHECK: | | `-FieldDecl {{.*}} AnonymousMember 'int' |
177 | // CHECK: | `-CXXRecordDecl {{.*}} struct Anonymous<A::B::C<void>> definition |
178 | // CHECK: | |-FieldDecl {{.*}} AnonymousMember 'int' |
179 | // CHECK: | `-CXXRecordDecl {{.*}} struct D definition |
180 | // CHECK: | `-FieldDecl {{.*}} AnonymousDMember 'int' |
181 | |
182 | int main(int argc, char **argv) { |
183 | AnonInt.AnonymousMember = 1; |
184 | AnonABCVoid.AnonymousMember = 2; |
185 | AnonABCVoidD.AnonymousDMember = 3; |
186 | |
187 | return 0; |
188 | } |
189 | |