TypeIndexDiscoveryTest.cpp 21 KB

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