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