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