• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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