1 //===- llvm/unittest/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp --------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
11
12 #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
13 #include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
14 #include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
15 #include "llvm/Support/Allocator.h"
16
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19
20 using namespace llvm;
21 using namespace llvm::codeview;
22
23 class TypeIndexIteratorTest : public testing::Test {
24 public:
TypeIndexIteratorTest()25 TypeIndexIteratorTest() {}
26
SetUp()27 void SetUp() override {
28 Refs.clear();
29 TTB = make_unique<AppendingTypeTableBuilder>(Storage);
30 CRB = make_unique<ContinuationRecordBuilder>();
31 Symbols.clear();
32 }
33
TearDown()34 void TearDown() override {
35 CRB.reset();
36 TTB.reset();
37 }
38
39 protected:
40 template <typename... Indices>
checkTypeReferences(uint32_t RecordIndex,Indices &&...TIs) const41 bool checkTypeReferences(uint32_t RecordIndex, Indices &&... TIs) const {
42 EXPECT_EQ(sizeof...(Indices), countRefs(RecordIndex));
43
44 // Choose between type or symbol records. The checking code doesn't care
45 // which we have.
46 std::vector<ArrayRef<uint8_t>> CVRecords;
47 if (Symbols.empty()) {
48 CVRecords = TTB->records();
49 } else {
50 for (const CVSymbol &S : Symbols)
51 CVRecords.push_back(S.data());
52 }
53
54 return checkTypeReferencesImpl(RecordIndex, CVRecords,
55 std::forward<Indices>(TIs)...);
56 }
57
writeFieldList(T &&...MemberRecords)58 template <typename... T> void writeFieldList(T &&... MemberRecords) {
59 CRB->begin(ContinuationRecordKind::FieldList);
60 writeFieldListImpl(std::forward<T>(MemberRecords)...);
61 auto Records = CRB->end(TTB->nextTypeIndex());
62 ASSERT_EQ(1u, Records.size());
63 TTB->insertRecordBytes(Records.front().RecordData);
64 discoverAllTypeIndices();
65 }
66
writeTypeRecords(T &&...Records)67 template <typename... T> void writeTypeRecords(T &&... Records) {
68 writeTypeRecordsImpl(std::forward<T>(Records)...);
69 ASSERT_EQ(sizeof...(T), TTB->records().size());
70 discoverAllTypeIndices();
71 }
72
writeSymbolRecords(T &&...Records)73 template <typename... T> void writeSymbolRecords(T &&... Records) {
74 writeSymbolRecordsImpl(std::forward<T>(Records)...);
75 ASSERT_EQ(sizeof...(T), Symbols.size());
76 discoverTypeIndicesInSymbols();
77 }
78
79 std::unique_ptr<AppendingTypeTableBuilder> TTB;
80
81 private:
countRefs(uint32_t RecordIndex) const82 uint32_t countRefs(uint32_t RecordIndex) const {
83 auto &R = Refs[RecordIndex];
84 uint32_t Count = 0;
85 for (auto &Ref : R) {
86 Count += Ref.Count;
87 }
88 return Count;
89 }
90
checkOneTypeReference(uint32_t RecordIndex,ArrayRef<uint8_t> RecordData,TypeIndex TI) const91 bool checkOneTypeReference(uint32_t RecordIndex, ArrayRef<uint8_t> RecordData,
92 TypeIndex TI) const {
93 RecordData = RecordData.drop_front(sizeof(RecordPrefix));
94 auto &RefList = Refs[RecordIndex];
95 for (auto &Ref : RefList) {
96 uint32_t Offset = Ref.Offset;
97 ArrayRef<uint8_t> Loc = RecordData.drop_front(Offset);
98 ArrayRef<TypeIndex> Indices(
99 reinterpret_cast<const TypeIndex *>(Loc.data()), Ref.Count);
100 if (llvm::any_of(Indices,
101 [TI](const TypeIndex &Other) { return Other == TI; }))
102 return true;
103 }
104 return false;
105 }
106
107 template <typename... Indices>
checkTypeReferencesImpl(uint32_t RecordIndex,ArrayRef<ArrayRef<uint8_t>> CVRecords) const108 bool checkTypeReferencesImpl(uint32_t RecordIndex,
109 ArrayRef<ArrayRef<uint8_t>> CVRecords) const {
110 return true;
111 }
112
113 template <typename... Indices>
checkTypeReferencesImpl(uint32_t RecordIndex,ArrayRef<ArrayRef<uint8_t>> CVRecords,TypeIndex TI,Indices &&...Rest) const114 bool checkTypeReferencesImpl(uint32_t RecordIndex,
115 ArrayRef<ArrayRef<uint8_t>> CVRecords,
116 TypeIndex TI, Indices &&... Rest) const {
117 ArrayRef<uint8_t> Record = CVRecords[RecordIndex];
118 bool Success = checkOneTypeReference(RecordIndex, Record, TI);
119 EXPECT_TRUE(Success);
120 return Success & checkTypeReferencesImpl(RecordIndex, CVRecords,
121 std::forward<Indices>(Rest)...);
122 }
123
discoverAllTypeIndices()124 void discoverAllTypeIndices() {
125 Refs.resize(TTB->records().size());
126 for (uint32_t I = 0; I < TTB->records().size(); ++I) {
127 ArrayRef<uint8_t> Data = TTB->records()[I];
128 discoverTypeIndices(Data, Refs[I]);
129 }
130 }
131
discoverTypeIndicesInSymbols()132 void discoverTypeIndicesInSymbols() {
133 Refs.resize(Symbols.size());
134 for (uint32_t I = 0; I < Symbols.size(); ++I)
135 discoverTypeIndicesInSymbol(Symbols[I], Refs[I]);
136 }
137
138 // Helper function to write out a field list record with the given list
139 // of member records.
writeFieldListImpl()140 void writeFieldListImpl() {}
141
142 template <typename RecType, typename... Rest>
writeFieldListImpl(RecType && Record,Rest &&...Records)143 void writeFieldListImpl(RecType &&Record, Rest &&... Records) {
144 CRB->writeMemberType(Record);
145 writeFieldListImpl(std::forward<Rest>(Records)...);
146 }
147
148 // Helper function to write out a list of type records.
writeTypeRecordsImpl()149 void writeTypeRecordsImpl() {}
150
151 template <typename RecType, typename... Rest>
writeTypeRecordsImpl(RecType && Record,Rest &&...Records)152 void writeTypeRecordsImpl(RecType &&Record, Rest &&... Records) {
153 TTB->writeLeafType(Record);
154 writeTypeRecordsImpl(std::forward<Rest>(Records)...);
155 }
156
157 // Helper function to write out a list of symbol records.
writeSymbolRecordsImpl()158 void writeSymbolRecordsImpl() {}
159
160 template <typename RecType, typename... Rest>
writeSymbolRecordsImpl(RecType && Record,Rest &&...Records)161 void writeSymbolRecordsImpl(RecType &&Record, Rest &&... Records) {
162 Symbols.push_back(SymbolSerializer::writeOneSymbol(Record, Storage,
163 CodeViewContainer::Pdb));
164 writeSymbolRecordsImpl(std::forward<Rest>(Records)...);
165 }
166
167 std::vector<SmallVector<TiReference, 4>> Refs;
168 std::unique_ptr<ContinuationRecordBuilder> CRB;
169 std::vector<CVSymbol> Symbols;
170 BumpPtrAllocator Storage;
171 };
172
173 namespace leafs {
174 static FuncIdRecord FuncId(TypeIndex(1), TypeIndex(2), "FuncId");
175 static MemberFuncIdRecord MemFuncId(TypeIndex(3), TypeIndex(4), "FuncId");
176 static StringIdRecord StringId(TypeIndex(5), "TheString");
177 static struct {
178 std::vector<TypeIndex> Ids = {TypeIndex(6), TypeIndex(7), TypeIndex(8)};
179 StringListRecord Record{TypeRecordKind::StringList, Ids};
180 } StringList;
181 static struct {
182 std::vector<TypeIndex> Ids = {TypeIndex(9), TypeIndex(10), TypeIndex(11)};
183 BuildInfoRecord Record{Ids};
184 } BuildInfo;
185 static UdtSourceLineRecord UdtSourceLine(TypeIndex(12), TypeIndex(13), 0);
186 static UdtModSourceLineRecord UdtModSourceLine(TypeIndex(14), TypeIndex(15), 0,
187 0);
188 static ModifierRecord Modifier(TypeIndex(16), ModifierOptions::None);
189 static ProcedureRecord Procedure(TypeIndex(17), CallingConvention::PpcCall,
190 FunctionOptions::None, 0, TypeIndex(18));
191 static MemberFunctionRecord MemberFunction(TypeIndex(19), TypeIndex(20),
192 TypeIndex(21),
193 CallingConvention::ThisCall,
194 FunctionOptions::None, 2,
195 TypeIndex(22), 0);
196 static struct {
197 std::vector<TypeIndex> Ids = {TypeIndex(23), TypeIndex(24), TypeIndex(25)};
198 ArgListRecord Record{TypeRecordKind::ArgList, Ids};
199 } ArgList;
200 static ArrayRecord Array(TypeIndex(26), TypeIndex(27), 10, "MyArray");
201 static ClassRecord Class(TypeRecordKind::Class, 3, ClassOptions::None,
202 TypeIndex(28), TypeIndex(29), TypeIndex(30), 10,
203 "MyClass", "MyClassUniqueName");
204 static ClassRecord Struct(TypeRecordKind::Struct, 3, ClassOptions::None,
205 TypeIndex(31), TypeIndex(32), TypeIndex(33), 10,
206 "MyClass", "MyClassUniqueName");
207 static UnionRecord Union(1, ClassOptions::None, TypeIndex(34), 10, "MyUnion",
208 "MyUnionUniqueName");
209 static EnumRecord Enum(1, ClassOptions::None, TypeIndex(35), "MyEnum",
210 "EnumUniqueName", TypeIndex(36));
211 static BitFieldRecord BitField(TypeIndex(37), 1, 0);
212 static VFTableRecord VFTable(TypeIndex(38), TypeIndex(39), 1, "VFT", {});
213 static VFTableShapeRecord VTableShape({});
214 static struct {
215 const TypeIndex T1{40};
216 const TypeIndex T2{41};
217 const TypeIndex T3{42};
218 const TypeIndex T4{43};
219
220 std::vector<OneMethodRecord> Methods{
221 {T1, MemberAccess::Public, MethodKind::IntroducingVirtual,
222 MethodOptions::None, 0, "Method1"},
223 {T2, MemberAccess::Public, MethodKind::PureVirtual, MethodOptions::None,
224 0, "Method1"},
225 {T3, MemberAccess::Public, MethodKind::PureIntroducingVirtual,
226 MethodOptions::None, 0, "Method1"},
227 {T4, MemberAccess::Public, MethodKind::Static, MethodOptions::None, 0,
228 "Method1"}};
229
230 MethodOverloadListRecord Record{Methods};
231 } MethodOverloadList;
232 static PointerRecord Pointer(TypeIndex(44), PointerKind::Near32,
233 PointerMode::Pointer, PointerOptions::Const, 3);
234 static PointerRecord MemberPointer(
235 TypeIndex(45), PointerKind::Near32, PointerMode::PointerToDataMember,
236 PointerOptions::Const, 3,
237 MemberPointerInfo(TypeIndex(46),
238 PointerToMemberRepresentation::GeneralData));
239 }
240
241 namespace members {
242 static BaseClassRecord BaseClass(MemberAccess::Public, TypeIndex(47), 0);
243 static EnumeratorRecord Enumerator(MemberAccess::Public,
244 APSInt(APInt(8, 3, false)), "Test");
245 DataMemberRecord DataMember(MemberAccess::Public, TypeIndex(48), 0, "Test");
246 OverloadedMethodRecord OverloadedMethod(3, TypeIndex(49), "MethodList");
247 static struct {
248 const TypeIndex T1{50};
249 const TypeIndex T2{51};
250 const TypeIndex T3{52};
251 const TypeIndex T4{53};
252 OneMethodRecord R1{T1,
253 MemberAccess::Public,
254 MethodKind::IntroducingVirtual,
255 MethodOptions::None,
256 0,
257 "M1"};
258 OneMethodRecord R2{T2,
259 MemberAccess::Public,
260 MethodKind::PureVirtual,
261 MethodOptions::None,
262 0,
263 "M2"};
264 OneMethodRecord R3{T3,
265 MemberAccess::Public,
266 MethodKind::PureIntroducingVirtual,
267 MethodOptions::None,
268 0,
269 "M3"};
270 OneMethodRecord R4{T4,
271 MemberAccess::Protected,
272 MethodKind::Vanilla,
273 MethodOptions::CompilerGenerated,
274 0,
275 "M4"};
276 } OneMethod;
277 static NestedTypeRecord NestedType(TypeIndex(54), "MyClass");
278 static StaticDataMemberRecord StaticDataMember(MemberAccess::Public,
279 TypeIndex(55), "Foo");
280 static VirtualBaseClassRecord VirtualBaseClass(TypeRecordKind::VirtualBaseClass,
281 MemberAccess::Public,
282 TypeIndex(56), TypeIndex(57), 0,
283 0);
284 static VFPtrRecord VFPtr(TypeIndex(58));
285 static ListContinuationRecord Continuation(TypeIndex(59));
286 }
287
TEST_F(TypeIndexIteratorTest,FuncId)288 TEST_F(TypeIndexIteratorTest, FuncId) {
289 using namespace leafs;
290 writeTypeRecords(FuncId);
291 checkTypeReferences(0, FuncId.FunctionType, FuncId.ParentScope);
292 }
293
TEST_F(TypeIndexIteratorTest,MemFuncId)294 TEST_F(TypeIndexIteratorTest, MemFuncId) {
295 using namespace leafs;
296 writeTypeRecords(MemFuncId);
297 checkTypeReferences(0, MemFuncId.ClassType, MemFuncId.FunctionType);
298 }
299
TEST_F(TypeIndexIteratorTest,StringId)300 TEST_F(TypeIndexIteratorTest, StringId) {
301 using namespace leafs;
302 writeTypeRecords(StringId);
303 checkTypeReferences(0, StringId.Id);
304 }
305
TEST_F(TypeIndexIteratorTest,SubstrList)306 TEST_F(TypeIndexIteratorTest, SubstrList) {
307 using namespace leafs;
308 writeTypeRecords(StringList.Record);
309 checkTypeReferences(0, StringList.Ids[0], StringList.Ids[1],
310 StringList.Ids[2]);
311 }
312
TEST_F(TypeIndexIteratorTest,BuildInfo)313 TEST_F(TypeIndexIteratorTest, BuildInfo) {
314 using namespace leafs;
315 writeTypeRecords(BuildInfo.Record);
316 checkTypeReferences(0, BuildInfo.Ids[0], BuildInfo.Ids[1], BuildInfo.Ids[2]);
317 }
318
TEST_F(TypeIndexIteratorTest,UdtSrcLine)319 TEST_F(TypeIndexIteratorTest, UdtSrcLine) {
320 using namespace leafs;
321 writeTypeRecords(UdtSourceLine);
322 checkTypeReferences(0, UdtSourceLine.UDT, UdtSourceLine.SourceFile);
323 }
324
TEST_F(TypeIndexIteratorTest,UdtModSrcLine)325 TEST_F(TypeIndexIteratorTest, UdtModSrcLine) {
326 using namespace leafs;
327 writeTypeRecords(UdtModSourceLine);
328 checkTypeReferences(0, UdtModSourceLine.UDT, UdtModSourceLine.SourceFile);
329 }
330
TEST_F(TypeIndexIteratorTest,Modifier)331 TEST_F(TypeIndexIteratorTest, Modifier) {
332 using namespace leafs;
333 writeTypeRecords(Modifier);
334 checkTypeReferences(0, Modifier.ModifiedType);
335 }
336
TEST_F(TypeIndexIteratorTest,Procedure)337 TEST_F(TypeIndexIteratorTest, Procedure) {
338 using namespace leafs;
339 writeTypeRecords(Procedure);
340 checkTypeReferences(0, Procedure.ReturnType, Procedure.ArgumentList);
341 }
342
TEST_F(TypeIndexIteratorTest,MemFunc)343 TEST_F(TypeIndexIteratorTest, MemFunc) {
344 using namespace leafs;
345 writeTypeRecords(MemberFunction);
346 checkTypeReferences(0, MemberFunction.ReturnType, MemberFunction.ClassType,
347 MemberFunction.ThisType, MemberFunction.ArgumentList);
348 }
349
TEST_F(TypeIndexIteratorTest,ArgList)350 TEST_F(TypeIndexIteratorTest, ArgList) {
351 using namespace leafs;
352 writeTypeRecords(ArgList.Record);
353 checkTypeReferences(0, ArgList.Ids[0], ArgList.Ids[1], ArgList.Ids[2]);
354 }
355
TEST_F(TypeIndexIteratorTest,Array)356 TEST_F(TypeIndexIteratorTest, Array) {
357 using namespace leafs;
358 writeTypeRecords(Array);
359 checkTypeReferences(0, Array.ElementType, Array.IndexType);
360 }
361
TEST_F(TypeIndexIteratorTest,Class)362 TEST_F(TypeIndexIteratorTest, Class) {
363 using namespace leafs;
364 writeTypeRecords(Class);
365 checkTypeReferences(0, Class.FieldList, Class.DerivationList,
366 Class.VTableShape);
367 }
368
TEST_F(TypeIndexIteratorTest,Struct)369 TEST_F(TypeIndexIteratorTest, Struct) {
370 using namespace leafs;
371 writeTypeRecords(Struct);
372 checkTypeReferences(0, Struct.FieldList, Struct.DerivationList,
373 Struct.VTableShape);
374 }
375
TEST_F(TypeIndexIteratorTest,Union)376 TEST_F(TypeIndexIteratorTest, Union) {
377 using namespace leafs;
378 writeTypeRecords(Union);
379 checkTypeReferences(0, Union.FieldList);
380 }
381
TEST_F(TypeIndexIteratorTest,Enum)382 TEST_F(TypeIndexIteratorTest, Enum) {
383 using namespace leafs;
384 writeTypeRecords(Enum);
385 checkTypeReferences(0, Enum.FieldList, Enum.UnderlyingType);
386 }
387
TEST_F(TypeIndexIteratorTest,Bitfield)388 TEST_F(TypeIndexIteratorTest, Bitfield) {
389 using namespace leafs;
390 writeTypeRecords(BitField);
391 checkTypeReferences(0, BitField.Type);
392 }
393
TEST_F(TypeIndexIteratorTest,VTable)394 TEST_F(TypeIndexIteratorTest, VTable) {
395 using namespace leafs;
396 writeTypeRecords(VFTable);
397 checkTypeReferences(0, VFTable.CompleteClass, VFTable.OverriddenVFTable);
398 }
399
TEST_F(TypeIndexIteratorTest,VTShape)400 TEST_F(TypeIndexIteratorTest, VTShape) {
401 using namespace leafs;
402 writeTypeRecords(VTableShape);
403 checkTypeReferences(0);
404 }
405
TEST_F(TypeIndexIteratorTest,OverloadList)406 TEST_F(TypeIndexIteratorTest, OverloadList) {
407 using namespace leafs;
408 writeTypeRecords(MethodOverloadList.Record);
409 checkTypeReferences(0, MethodOverloadList.T1, MethodOverloadList.T2,
410 MethodOverloadList.T3, MethodOverloadList.T4);
411 }
412
TEST_F(TypeIndexIteratorTest,Pointer)413 TEST_F(TypeIndexIteratorTest, Pointer) {
414 using namespace leafs;
415 writeTypeRecords(Pointer);
416 checkTypeReferences(0, Pointer.ReferentType);
417 }
418
TEST_F(TypeIndexIteratorTest,MemberPointer)419 TEST_F(TypeIndexIteratorTest, MemberPointer) {
420 using namespace leafs;
421 writeTypeRecords(MemberPointer);
422 checkTypeReferences(0, MemberPointer.ReferentType,
423 MemberPointer.MemberInfo->ContainingType);
424 }
425
TEST_F(TypeIndexIteratorTest,ManyTypes)426 TEST_F(TypeIndexIteratorTest, ManyTypes) {
427
428 using namespace leafs;
429 writeTypeRecords(FuncId, MemFuncId, StringId, StringList.Record,
430 BuildInfo.Record, UdtSourceLine, UdtModSourceLine, Modifier,
431 Procedure, MemberFunction, ArgList.Record, Array, Class,
432 Union, Enum, BitField, VFTable, VTableShape,
433 MethodOverloadList.Record, Pointer, MemberPointer);
434
435 checkTypeReferences(0, FuncId.FunctionType, FuncId.ParentScope);
436 checkTypeReferences(1, MemFuncId.ClassType, MemFuncId.FunctionType);
437 checkTypeReferences(2, StringId.Id);
438 checkTypeReferences(3, StringList.Ids[0], StringList.Ids[1],
439 StringList.Ids[2]);
440 checkTypeReferences(4, BuildInfo.Ids[0], BuildInfo.Ids[1], BuildInfo.Ids[2]);
441 checkTypeReferences(5, UdtSourceLine.UDT, UdtSourceLine.SourceFile);
442 checkTypeReferences(6, UdtModSourceLine.UDT, UdtModSourceLine.SourceFile);
443 checkTypeReferences(7, Modifier.ModifiedType);
444 checkTypeReferences(8, Procedure.ReturnType, Procedure.ArgumentList);
445 checkTypeReferences(9, MemberFunction.ReturnType, MemberFunction.ClassType,
446 MemberFunction.ThisType, MemberFunction.ArgumentList);
447 checkTypeReferences(10, ArgList.Ids[0], ArgList.Ids[1], ArgList.Ids[2]);
448 checkTypeReferences(11, Array.ElementType, Array.IndexType);
449 checkTypeReferences(12, Class.FieldList, Class.DerivationList,
450 Class.VTableShape);
451 checkTypeReferences(13, Union.FieldList);
452 checkTypeReferences(14, Enum.FieldList, Enum.UnderlyingType);
453 checkTypeReferences(15, BitField.Type);
454 checkTypeReferences(16, VFTable.CompleteClass, VFTable.OverriddenVFTable);
455 checkTypeReferences(17);
456 checkTypeReferences(18, MethodOverloadList.T1, MethodOverloadList.T2,
457 MethodOverloadList.T3, MethodOverloadList.T4);
458 checkTypeReferences(19, Pointer.ReferentType);
459 checkTypeReferences(20, MemberPointer.ReferentType,
460 MemberPointer.MemberInfo->ContainingType);
461 }
462
TEST_F(TypeIndexIteratorTest,FieldListBaseClass)463 TEST_F(TypeIndexIteratorTest, FieldListBaseClass) {
464 using namespace members;
465 writeFieldList(BaseClass);
466 checkTypeReferences(0, BaseClass.Type);
467 }
468
TEST_F(TypeIndexIteratorTest,FieldListEnumerator)469 TEST_F(TypeIndexIteratorTest, FieldListEnumerator) {
470 using namespace members;
471 writeFieldList(Enumerator);
472 checkTypeReferences(0);
473 }
474
TEST_F(TypeIndexIteratorTest,FieldListMember)475 TEST_F(TypeIndexIteratorTest, FieldListMember) {
476 using namespace members;
477 writeFieldList(DataMember);
478 checkTypeReferences(0, DataMember.Type);
479 }
480
TEST_F(TypeIndexIteratorTest,FieldListMethod)481 TEST_F(TypeIndexIteratorTest, FieldListMethod) {
482 using namespace members;
483 writeFieldList(OverloadedMethod);
484 checkTypeReferences(0, OverloadedMethod.MethodList);
485 }
486
TEST_F(TypeIndexIteratorTest,FieldListOneMethod)487 TEST_F(TypeIndexIteratorTest, FieldListOneMethod) {
488 using namespace members;
489 writeFieldList(OneMethod.R1, OneMethod.R2, OneMethod.R3, OneMethod.R4);
490 checkTypeReferences(0, OneMethod.T1, OneMethod.T2, OneMethod.T3,
491 OneMethod.T4);
492 }
493
TEST_F(TypeIndexIteratorTest,FieldListNestedType)494 TEST_F(TypeIndexIteratorTest, FieldListNestedType) {
495 using namespace members;
496 writeFieldList(NestedType);
497 checkTypeReferences(0, NestedType.Type);
498 }
499
TEST_F(TypeIndexIteratorTest,FieldListStaticMember)500 TEST_F(TypeIndexIteratorTest, FieldListStaticMember) {
501 using namespace members;
502 writeFieldList(StaticDataMember);
503 checkTypeReferences(0, StaticDataMember.Type);
504 }
505
TEST_F(TypeIndexIteratorTest,FieldListVirtualBase)506 TEST_F(TypeIndexIteratorTest, FieldListVirtualBase) {
507 using namespace members;
508 writeFieldList(VirtualBaseClass);
509 checkTypeReferences(0, VirtualBaseClass.BaseType, VirtualBaseClass.VBPtrType);
510 }
511
TEST_F(TypeIndexIteratorTest,FieldListVFTable)512 TEST_F(TypeIndexIteratorTest, FieldListVFTable) {
513 using namespace members;
514 writeFieldList(VFPtr);
515 checkTypeReferences(0, VFPtr.Type);
516 }
517
TEST_F(TypeIndexIteratorTest,FieldListContinuation)518 TEST_F(TypeIndexIteratorTest, FieldListContinuation) {
519 using namespace members;
520 writeFieldList(Continuation);
521 checkTypeReferences(0, Continuation.ContinuationIndex);
522 }
523
TEST_F(TypeIndexIteratorTest,ManyMembers)524 TEST_F(TypeIndexIteratorTest, ManyMembers) {
525 using namespace members;
526 writeFieldList(BaseClass, Enumerator, DataMember, OverloadedMethod,
527 OneMethod.R1, OneMethod.R2, OneMethod.R3, OneMethod.R4,
528 NestedType, StaticDataMember, VirtualBaseClass, VFPtr,
529 Continuation);
530
531 checkTypeReferences(
532 0, BaseClass.Type, DataMember.Type, OverloadedMethod.MethodList,
533 OneMethod.T1, OneMethod.T2, OneMethod.T3, OneMethod.T4, NestedType.Type,
534 StaticDataMember.Type, VirtualBaseClass.BaseType,
535 VirtualBaseClass.VBPtrType, VFPtr.Type, Continuation.ContinuationIndex);
536 }
537
TEST_F(TypeIndexIteratorTest,ProcSym)538 TEST_F(TypeIndexIteratorTest, ProcSym) {
539 ProcSym GS(SymbolRecordKind::GlobalProcSym);
540 GS.FunctionType = TypeIndex::Float32();
541 ProcSym LS(SymbolRecordKind::ProcSym);
542 LS.FunctionType = TypeIndex::Float64();
543 writeSymbolRecords(GS, LS);
544 checkTypeReferences(0, GS.FunctionType);
545 checkTypeReferences(1, LS.FunctionType);
546 }
547
TEST_F(TypeIndexIteratorTest,DataSym)548 TEST_F(TypeIndexIteratorTest, DataSym) {
549 DataSym DS(SymbolRecordKind::GlobalData);
550 DS.Type = TypeIndex::Float32();
551 writeSymbolRecords(DS);
552 checkTypeReferences(0, DS.Type);
553 }
554
TEST_F(TypeIndexIteratorTest,RegisterSym)555 TEST_F(TypeIndexIteratorTest, RegisterSym) {
556 RegisterSym Reg(SymbolRecordKind::RegisterSym);
557 Reg.Index = TypeIndex::UInt32();
558 Reg.Register = RegisterId::CVRegEAX;
559 Reg.Name = "Target";
560 writeSymbolRecords(Reg);
561 checkTypeReferences(0, Reg.Index);
562 }
563
TEST_F(TypeIndexIteratorTest,CallerSym)564 TEST_F(TypeIndexIteratorTest, CallerSym) {
565 CallerSym Callees(SymbolRecordKind::CalleeSym);
566 Callees.Indices.push_back(TypeIndex(1));
567 Callees.Indices.push_back(TypeIndex(2));
568 Callees.Indices.push_back(TypeIndex(3));
569 CallerSym Callers(SymbolRecordKind::CallerSym);
570 Callers.Indices.push_back(TypeIndex(4));
571 Callers.Indices.push_back(TypeIndex(5));
572 Callers.Indices.push_back(TypeIndex(6));
573 CallerSym Inlinees(SymbolRecordKind::InlineesSym);
574 Inlinees.Indices.push_back(TypeIndex(7));
575 Inlinees.Indices.push_back(TypeIndex(8));
576 Inlinees.Indices.push_back(TypeIndex(9));
577 writeSymbolRecords(Callees, Callers, Inlinees);
578 checkTypeReferences(0, TypeIndex(1), TypeIndex(2), TypeIndex(3));
579 checkTypeReferences(1, TypeIndex(4), TypeIndex(5), TypeIndex(6));
580 checkTypeReferences(2, TypeIndex(7), TypeIndex(8), TypeIndex(9));
581 }
582
TEST_F(TypeIndexIteratorTest,Precomp)583 TEST_F(TypeIndexIteratorTest, Precomp) {
584 PrecompRecord P(TypeRecordKind::Precomp);
585 P.StartTypeIndex = TypeIndex::FirstNonSimpleIndex;
586 P.TypesCount = 100;
587 P.Signature = 0x12345678;
588 P.PrecompFilePath = "C:/precomp.obj";
589
590 EndPrecompRecord EP(TypeRecordKind::EndPrecomp);
591 EP.Signature = P.Signature;
592
593 writeTypeRecords(P, EP);
594 checkTypeReferences(0);
595 }
596
597 // This is a test for getEncodedIntegerLength()
TEST_F(TypeIndexIteratorTest,VariableSizeIntegers)598 TEST_F(TypeIndexIteratorTest, VariableSizeIntegers) {
599 BaseClassRecord BaseClass1(MemberAccess::Public, TypeIndex(47), (uint64_t)-1);
600 BaseClassRecord BaseClass2(MemberAccess::Public, TypeIndex(48), 1);
601 writeFieldList(BaseClass1, BaseClass2);
602 checkTypeReferences(0, TypeIndex(47), TypeIndex(48));
603 }
604
TEST_F(TypeIndexIteratorTest,UsingNamespace)605 TEST_F(TypeIndexIteratorTest, UsingNamespace) {
606 UsingNamespaceSym UN(SymbolRecordKind::UsingNamespaceSym);
607 UN.Name = "std";
608 writeSymbolRecords(UN);
609 checkTypeReferences(0);
610 }
611