OSDN Git Service

[PDB] Refactor the PDB symbol classes to fix a reuse bug.
authorZachary Turner <zturner@google.com>
Wed, 5 Sep 2018 23:30:38 +0000 (23:30 +0000)
committerZachary Turner <zturner@google.com>
Wed, 5 Sep 2018 23:30:38 +0000 (23:30 +0000)
The way DIA SDK works is that when you request a symbol, it
gets assigned an internal identifier that is unique for the
life of the session.  You can then use this identifier to
get back the same symbol, with all of the same internal state
that it had before, even if you "destroyed" the original
copy of the object you had.

This didn't work properly in our native implementation, and
if you destroyed an object for a particular symbol, then
requested the same symbol again, it would get assigned a new
ID and you'd get a fresh copy of the object.  In order to fix
this some refactoring had to happen to properly reuse cached
objects.  Some unittests are added to verify that symbol
reuse is taking place, making use of the new unittest input
feature.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@341503 91177308-0d34-0410-b5e6-96231b3b80d8

81 files changed:
include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h
include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h
include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
include/llvm/DebugInfo/PDB/Native/NativeSession.h
include/llvm/DebugInfo/PDB/PDBSymbol.h
include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h
include/llvm/DebugInfo/PDB/PDBSymbolBlock.h
include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h
include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h
include/llvm/DebugInfo/PDB/PDBSymbolCustom.h
include/llvm/DebugInfo/PDB/PDBSymbolData.h
include/llvm/DebugInfo/PDB/PDBSymbolExe.h
include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h
include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h
include/llvm/DebugInfo/PDB/PDBSymbolLabel.h
include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h
include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h
include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h
include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h
lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp
lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp
lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp
lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp
lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
lib/DebugInfo/PDB/Native/NativeSession.cpp
lib/DebugInfo/PDB/PDBSymbol.cpp
lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp
lib/DebugInfo/PDB/PDBSymbolBlock.cpp
lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp
lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp
lib/DebugInfo/PDB/PDBSymbolCustom.cpp
lib/DebugInfo/PDB/PDBSymbolData.cpp
lib/DebugInfo/PDB/PDBSymbolExe.cpp
lib/DebugInfo/PDB/PDBSymbolFunc.cpp
lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp
lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp
lib/DebugInfo/PDB/PDBSymbolLabel.cpp
lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp
lib/DebugInfo/PDB/PDBSymbolThunk.cpp
lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp
lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp
lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp
lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp
lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp
lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp
lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp
lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp
lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp
lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp
lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp
lib/DebugInfo/PDB/PDBSymbolUnknown.cpp
lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp
tools/llvm-pdbutil/llvm-pdbutil.cpp
unittests/DebugInfo/PDB/CMakeLists.txt
unittests/DebugInfo/PDB/Inputs/empty.pdb [new file with mode: 0644]
unittests/DebugInfo/PDB/NativeSymbolReuseTest.cpp [new file with mode: 0644]

index 6aa1460..e213bbe 100644 (file)
 #define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMMODULES_H
 
 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
-#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
 namespace llvm {
 namespace pdb {
 
-class DbiModuleList;
 class NativeSession;
 
 class NativeEnumModules : public IPDBEnumChildren<PDBSymbol> {
 public:
-  NativeEnumModules(NativeSession &Session, const DbiModuleList &Modules,
-                    uint32_t Index = 0);
+  NativeEnumModules(NativeSession &Session, uint32_t Index = 0);
 
   uint32_t getChildCount() const override;
   std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
@@ -32,7 +29,6 @@ public:
 
 private:
   NativeSession &Session;
-  const DbiModuleList &Modules;
   uint32_t Index;
 };
 }
index 587c7ff..634eb75 100644 (file)
@@ -16,6 +16,8 @@
 namespace llvm {
 namespace pdb {
 
+class DbiStream;
+
 class NativeExeSymbol : public NativeRawSymbol {
 public:
   NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId);
@@ -31,8 +33,16 @@ public:
   bool hasCTypes() const override;
   bool hasPrivateSymbols() const override;
 
+  std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index);
+  uint32_t getNumCompilands() const;
+
 private:
   PDBFile &File;
+
+  DbiStream *Dbi = nullptr;
+
+  // EXE symbol is the authority on the various symbol types.
+  mutable std::vector<SymIndexId> Compilands;
 };
 
 } // namespace pdb
index 5b70ecf..cd7f52c 100644 (file)
@@ -23,7 +23,8 @@ typedef uint32_t SymIndexId;
 
 class NativeRawSymbol : public IPDBRawSymbol {
 public:
-  NativeRawSymbol(NativeSession &PDBSession, SymIndexId SymbolId);
+  NativeRawSymbol(NativeSession &PDBSession, PDB_SymType Tag,
+                  SymIndexId SymbolId);
 
   virtual std::unique_ptr<NativeRawSymbol> clone() const = 0;
 
@@ -230,6 +231,7 @@ public:
 
 protected:
   NativeSession &Session;
+  PDB_SymType Tag;
   SymIndexId SymbolId;
 };
 
index aff7ef2..398157a 100644 (file)
@@ -15,7 +15,6 @@
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
 #include "llvm/DebugInfo/PDB/IPDBSession.h"
-#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
 #include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
 #include "llvm/Support/Allocator.h"
@@ -25,6 +24,7 @@ namespace llvm {
 class MemoryBuffer;
 namespace pdb {
 class PDBFile;
+class NativeExeSymbol;
 
 class NativeSession : public IPDBSession {
 public:
@@ -37,8 +37,16 @@ public:
   static Error createFromExe(StringRef Path,
                              std::unique_ptr<IPDBSession> &Session);
 
-  std::unique_ptr<PDBSymbolCompiland>
-  createCompilandSymbol(DbiModuleDescriptor MI);
+  template <typename ConcreteSymbolT, typename... Args>
+  SymIndexId createSymbol(Args &&... ConstructorArgs) {
+    SymIndexId Id = SymbolCache.size();
+    std::unique_ptr<ConcreteSymbolT> Symbol =
+        llvm::make_unique<ConcreteSymbolT>(
+            *this, Id, std::forward<Args>(ConstructorArgs)...);
+    std::unique_ptr<NativeRawSymbol> NRS = std::move(Symbol);
+    SymbolCache.push_back(std::move(NRS));
+    return Id;
+  }
 
   std::unique_ptr<PDBSymbolTypeEnum>
   createEnumSymbol(codeview::TypeIndex Index);
@@ -107,7 +115,11 @@ public:
   PDBFile &getPDBFile() { return *Pdb; }
   const PDBFile &getPDBFile() const { return *Pdb; }
 
+  NativeExeSymbol &getNativeGlobalScope();
+
 private:
+  SymIndexId ExeSymbol = 0;
+
   std::unique_ptr<PDBFile> Pdb;
   std::unique_ptr<BumpPtrAllocator> Allocator;
   std::vector<std::unique_ptr<NativeRawSymbol>> SymbolCache;
index 0437346..9861e81 100644 (file)
@@ -49,9 +49,22 @@ class IPDBRawSymbol;
 class IPDBSession;
 
 #define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue)                             \
+private:                                                                       \
+  using PDBSymbol::PDBSymbol;                                                  \
+  friend class PDBSymbol;                                                      \
+                                                                               \
+public:                                                                        \
   static const PDB_SymType Tag = TagValue;                                     \
   static bool classof(const PDBSymbol *S) { return S->getSymTag() == Tag; }
 
+#define DECLARE_PDB_SYMBOL_CUSTOM_TYPE(Condition)                              \
+private:                                                                       \
+  using PDBSymbol::PDBSymbol;                                                  \
+  friend class PDBSymbol;                                                      \
+                                                                               \
+public:                                                                        \
+  static bool classof(const PDBSymbol *S) { return Condition; }
+
 /// PDBSymbol defines the base of the inheritance hierarchy for concrete symbol
 /// types (e.g. functions, executables, vtables, etc).  All concrete symbol
 /// types inherit from PDBSymbol and expose the exact set of methods that are
@@ -59,14 +72,33 @@ class IPDBSession;
 /// reference "Lexical and Class Hierarchy of Symbol Types":
 /// https://msdn.microsoft.com/en-us/library/370hs6k4.aspx
 class PDBSymbol {
+  static std::unique_ptr<PDBSymbol> createSymbol(const IPDBSession &PDBSession,
+                                                 PDB_SymType Tag);
+
 protected:
-  PDBSymbol(const IPDBSession &PDBSession,
-            std::unique_ptr<IPDBRawSymbol> Symbol);
-  PDBSymbol(PDBSymbol &Symbol);
+  explicit PDBSymbol(const IPDBSession &PDBSession);
+  PDBSymbol(PDBSymbol &&Other);
 
 public:
   static std::unique_ptr<PDBSymbol>
-  create(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol);
+  create(const IPDBSession &PDBSession,
+         std::unique_ptr<IPDBRawSymbol> RawSymbol);
+  static std::unique_ptr<PDBSymbol> create(const IPDBSession &PDBSession,
+                                           IPDBRawSymbol &RawSymbol);
+
+  template <typename ConcreteT>
+  static std::unique_ptr<ConcreteT>
+  createAs(const IPDBSession &PDBSession,
+           std::unique_ptr<IPDBRawSymbol> RawSymbol) {
+    std::unique_ptr<PDBSymbol> S = create(PDBSession, std::move(RawSymbol));
+    return unique_dyn_cast_or_null<ConcreteT>(std::move(S));
+  }
+  template <typename ConcreteT>
+  static std::unique_ptr<ConcreteT> createAs(const IPDBSession &PDBSession,
+                                             IPDBRawSymbol &RawSymbol) {
+    std::unique_ptr<PDBSymbol> S = create(PDBSession, RawSymbol);
+    return unique_dyn_cast_or_null<ConcreteT>(std::move(S));
+  }
 
   virtual ~PDBSymbol();
 
@@ -131,7 +163,8 @@ protected:
   }
 
   const IPDBSession &Session;
-  std::unique_ptr<IPDBRawSymbol> RawSymbol;
+  std::unique_ptr<IPDBRawSymbol> OwnedRawSymbol;
+  IPDBRawSymbol *RawSymbol = nullptr;
 };
 
 } // namespace llvm
index 3169146..ef00df1 100644 (file)
@@ -18,12 +18,9 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolAnnotation : public PDBSymbol {
-public:
-  PDBSymbolAnnotation(const IPDBSession &PDBSession,
-                      std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Annotation)
 
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getAddressOffset)
index d81da1e..2cf9c72 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolBlock : public PDBSymbol {
-public:
-  PDBSymbolBlock(const IPDBSession &PDBSession,
-                 std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Block)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getAddressOffset)
index 9549089..04dbd96 100644 (file)
@@ -20,12 +20,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolCompiland : public PDBSymbol {
-public:
-  PDBSymbolCompiland(const IPDBSession &PDBSession,
-                     std::unique_ptr<IPDBRawSymbol> CompilandSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Compiland)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled)
index dba50c4..3d651a4 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolCompilandDetails : public PDBSymbol {
-public:
-  PDBSymbolCompilandDetails(const IPDBSession &PDBSession,
-                            std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandDetails)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   void getFrontEndVersion(VersionInfo &Version) const {
index 7868f04..ffc4083 100644 (file)
@@ -18,12 +18,8 @@ namespace llvm {
 class raw_ostream;
 namespace pdb {
 class PDBSymbolCompilandEnv : public PDBSymbol {
-public:
-  PDBSymbolCompilandEnv(const IPDBSession &PDBSession,
-                        std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandEnv)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
index 54f0894..c29e4c3 100644 (file)
@@ -23,12 +23,8 @@ namespace pdb {
 /// fit anywhere else in the lexical hierarchy.
 /// https://msdn.microsoft.com/en-us/library/d88sf09h.aspx
 class PDBSymbolCustom : public PDBSymbol {
-public:
-  PDBSymbolCustom(const IPDBSession &PDBSession,
-                  std::unique_ptr<IPDBRawSymbol> CustomSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Custom)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes);
index 76b14bf..217e1e9 100644 (file)
@@ -21,12 +21,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolData : public PDBSymbol {
-public:
-  PDBSymbolData(const IPDBSession &PDBSession,
-                std::unique_ptr<IPDBRawSymbol> DataSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Data)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getAccess)
index 2c2d746..366d0cf 100644 (file)
@@ -20,12 +20,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolExe : public PDBSymbol {
-public:
-  PDBSymbolExe(const IPDBSession &PDBSession,
-               std::unique_ptr<IPDBRawSymbol> ExeSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Exe)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getAge)
index 05d585d..129e557 100644 (file)
@@ -22,18 +22,14 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolFunc : public PDBSymbol {
+  DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function)
 public:
-  PDBSymbolFunc(const IPDBSession &PDBSession,
-                std::unique_ptr<IPDBRawSymbol> FuncSymbol);
-
   void dump(PDBSymDumper &Dumper) const override;
 
   bool isDestructor() const;
 
   std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> getArguments() const;
 
-  DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function)
-
   FORWARD_SYMBOL_METHOD(getAccess)
   FORWARD_SYMBOL_METHOD(getAddressOffset)
   FORWARD_SYMBOL_METHOD(getAddressSection)
index 3341bd9..18db8a5 100644 (file)
@@ -20,12 +20,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolFuncDebugEnd : public PDBSymbol {
-public:
-  PDBSymbolFuncDebugEnd(const IPDBSession &PDBSession,
-                        std::unique_ptr<IPDBRawSymbol> FuncDebugEndSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugEnd)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getAddressOffset)
index 6729838..83d82f0 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolFuncDebugStart : public PDBSymbol {
-public:
-  PDBSymbolFuncDebugStart(const IPDBSession &PDBSession,
-                          std::unique_ptr<IPDBRawSymbol> FuncDebugStartSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugStart)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getAddressOffset)
index c2b1c28..8b2617f 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolLabel : public PDBSymbol {
-public:
-  PDBSymbolLabel(const IPDBSession &PDBSession,
-                 std::unique_ptr<IPDBRawSymbol> LabelSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Label)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getAddressOffset)
index c9e6ee6..9def3ed 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolPublicSymbol : public PDBSymbol {
-public:
-  PDBSymbolPublicSymbol(const IPDBSession &PDBSession,
-                        std::unique_ptr<IPDBRawSymbol> PublicSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PublicSymbol)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getAddressOffset)
index 614fad8..7bb0555 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolThunk : public PDBSymbol {
-public:
-  PDBSymbolThunk(const IPDBSession &PDBSession,
-                 std::unique_ptr<IPDBRawSymbol> ThunkSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Thunk)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getAccess)
index 39b7d3b..488f668 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeArray : public PDBSymbol {
-public:
-  PDBSymbolTypeArray(const IPDBSession &PDBSession,
-                     std::unique_ptr<IPDBRawSymbol> ArrayTypeSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ArrayType)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
   void dumpRight(PDBSymDumper &Dumper) const override;
 
index d607a3d..550deed 100644 (file)
@@ -22,12 +22,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeBaseClass : public PDBSymbol {
-public:
-  PDBSymbolTypeBaseClass(const IPDBSession &PDBSession,
-                         std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BaseClass)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getAccess)
index 5b1863c..e07e888 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeBuiltin : public PDBSymbol {
-public:
-  PDBSymbolTypeBuiltin(const IPDBSession &PDBSession,
-                       std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BuiltinType)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getBuiltinType)
index 199b3f8..0d8979c 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeCustom : public PDBSymbol {
-public:
-  PDBSymbolTypeCustom(const IPDBSession &PDBSession,
-                      std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CustomType)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getOemId)
index e635eb5..58292a6 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeDimension : public PDBSymbol {
-public:
-  PDBSymbolTypeDimension(const IPDBSession &PDBSession,
-                         std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Dimension)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getLowerBoundId)
index ddbe7e5..d8afba6 100644 (file)
@@ -21,12 +21,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeEnum : public PDBSymbol {
-public:
-  PDBSymbolTypeEnum(const IPDBSession &PDBSession,
-                    std::unique_ptr<IPDBRawSymbol> EnumTypeSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Enum)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getBuiltinType)
index 24c1312..5b940b0 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeFriend : public PDBSymbol {
-public:
-  PDBSymbolTypeFriend(const IPDBSession &PDBSession,
-                      std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Friend)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_ID_METHOD(getClassParent)
index 3855999..074cb41 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeFunctionArg : public PDBSymbol {
-public:
-  PDBSymbolTypeFunctionArg(const IPDBSession &PDBSession,
-                           std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionArg)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_ID_METHOD(getClassParent)
index abd4cf5..dfdf436 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeFunctionSig : public PDBSymbol {
-public:
-  PDBSymbolTypeFunctionSig(const IPDBSession &PDBSession,
-                           std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig)
-
+public:
   std::unique_ptr<IPDBEnumSymbols> getArguments() const;
 
   void dump(PDBSymDumper &Dumper) const override;
index 31cf536..d716abd 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeManaged : public PDBSymbol {
-public:
-  PDBSymbolTypeManaged(const IPDBSession &PDBSession,
-                       std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ManagedType)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getName)
index 7612eba..9bc0b16 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypePointer : public PDBSymbol {
-public:
-  PDBSymbolTypePointer(const IPDBSession &PDBSession,
-                       std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PointerType)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
   void dumpRight(PDBSymDumper &Dumper) const override;
 
index 16c1d1b..d6e2a36 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeTypedef : public PDBSymbol {
-public:
-  PDBSymbolTypeTypedef(const IPDBSession &PDBSession,
-                       std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Typedef)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(getBuiltinType)
index e259b6d..acd97bc 100644 (file)
@@ -23,17 +23,13 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeUDT : public PDBSymbol {
+  DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT)
 public:
-  PDBSymbolTypeUDT(const IPDBSession &PDBSession,
-                   std::unique_ptr<IPDBRawSymbol> UDTSymbol);
-
   std::unique_ptr<PDBSymbolTypeUDT> clone() const {
     return getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
         getSymIndexId());
   }
 
-  DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT)
-
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_ID_METHOD(getClassParent)
index e270c2b..6efce4b 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeVTable : public PDBSymbol {
-public:
-  PDBSymbolTypeVTable(const IPDBSession &PDBSession,
-                      std::unique_ptr<IPDBRawSymbol> VtblSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTable)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_ID_METHOD(getClassParent)
index 8acaabe..8949052 100644 (file)
@@ -19,12 +19,8 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolTypeVTableShape : public PDBSymbol {
-public:
-  PDBSymbolTypeVTableShape(const IPDBSession &PDBSession,
-                           std::unique_ptr<IPDBRawSymbol> VtblShapeSymbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTableShape)
-
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_METHOD(isConstType)
index de43e47..e935ac6 100644 (file)
@@ -18,16 +18,11 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolUnknown : public PDBSymbol {
-public:
-  PDBSymbolUnknown(const IPDBSession &PDBSession,
-                   std::unique_ptr<IPDBRawSymbol> UnknownSymbol);
+  DECLARE_PDB_SYMBOL_CUSTOM_TYPE(S->getSymTag() == PDB_SymType::None ||
+                                 S->getSymTag() >= PDB_SymType::Max)
 
+public:
   void dump(PDBSymDumper &Dumper) const override;
-
-  static bool classof(const PDBSymbol *S) {
-    return (S->getSymTag() == PDB_SymType::None ||
-            S->getSymTag() >= PDB_SymType::Max);
-  }
 };
 
 } // namespace llvm
index 70fbd5b..4e8c99f 100644 (file)
@@ -19,12 +19,9 @@ class raw_ostream;
 namespace pdb {
 
 class PDBSymbolUsingNamespace : public PDBSymbol {
-public:
-  PDBSymbolUsingNamespace(const IPDBSession &PDBSession,
-                          std::unique_ptr<IPDBRawSymbol> Symbol);
-
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UsingNamespace)
 
+public:
   void dump(PDBSymDumper &Dumper) const override;
 
   FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
index 7d6cb25..4072a0b 100644 (file)
@@ -852,7 +852,7 @@ DIARawSymbol::getVirtualBaseTableType() const {
 
   auto RawVT = llvm::make_unique<DIARawSymbol>(Session, TableType);
   auto Pointer =
-      llvm::make_unique<PDBSymbolTypePointer>(Session, std::move(RawVT));
+      PDBSymbol::createAs<PDBSymbolTypePointer>(Session, std::move(RawVT));
   return unique_dyn_cast<PDBSymbolTypeBuiltin>(Pointer->getPointeeType());
 }
 
index b7dc49f..8e233ca 100644 (file)
@@ -25,7 +25,7 @@ std::unique_ptr<PDBSymbolCompiland> DIASectionContrib::getCompiland() const {
     return nullptr;
 
   auto RawSymbol = llvm::make_unique<DIARawSymbol>(Session, Symbol);
-  return llvm::make_unique<PDBSymbolCompiland>(Session, std::move(RawSymbol));
+  return PDBSymbol::createAs<PDBSymbolCompiland>(Session, std::move(RawSymbol));
 }
 
 template <typename ArgType>
index 4644ddc..81e35e5 100644 (file)
@@ -16,8 +16,8 @@ namespace pdb {
 NativeBuiltinSymbol::NativeBuiltinSymbol(NativeSession &PDBSession,
                                          SymIndexId Id, PDB_BuiltinType T,
                                          uint64_t L)
-    : NativeRawSymbol(PDBSession, Id), Session(PDBSession), Type(T), Length(L) {
-}
+    : NativeRawSymbol(PDBSession, PDB_SymType::BuiltinType, Id),
+      Session(PDBSession), Type(T), Length(L) {}
 
 NativeBuiltinSymbol::~NativeBuiltinSymbol() {}
 
index 7132a99..da22a0e 100644 (file)
@@ -17,7 +17,7 @@ namespace pdb {
 NativeCompilandSymbol::NativeCompilandSymbol(NativeSession &Session,
                                              SymIndexId SymbolId,
                                              DbiModuleDescriptor MI)
-    : NativeRawSymbol(Session, SymbolId), Module(MI) {}
+    : NativeRawSymbol(Session, PDB_SymType::Compiland, SymbolId), Module(MI) {}
 
 PDB_SymType NativeCompilandSymbol::getSymTag() const {
   return PDB_SymType::Compiland;
index a65782e..f545688 100644 (file)
 #include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
 
 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
-#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
 
 namespace llvm {
 namespace pdb {
 
-NativeEnumModules::NativeEnumModules(NativeSession &PDBSession,
-                                     const DbiModuleList &Modules,
-                                     uint32_t Index)
-    : Session(PDBSession), Modules(Modules), Index(Index) {}
+NativeEnumModules::NativeEnumModules(NativeSession &PDBSession, uint32_t Index)
+    : Session(PDBSession), Index(Index) {}
 
 uint32_t NativeEnumModules::getChildCount() const {
-  return static_cast<uint32_t>(Modules.getModuleCount());
+  return Session.getNativeGlobalScope().getNumCompilands();
 }
 
 std::unique_ptr<PDBSymbol>
-NativeEnumModules::getChildAtIndex(uint32_t Index) const {
-  if (Index >= Modules.getModuleCount())
-    return nullptr;
-  return Session.createCompilandSymbol(Modules.getModuleDescriptor(Index));
+NativeEnumModules::getChildAtIndex(uint32_t N) const {
+  return Session.getNativeGlobalScope().getOrCreateCompiland(N);
 }
 
 std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() {
-  if (Index >= Modules.getModuleCount())
+  if (Index >= getChildCount())
     return nullptr;
   return getChildAtIndex(Index++);
 }
@@ -44,7 +41,7 @@ std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() {
 void NativeEnumModules::reset() { Index = 0; }
 
 NativeEnumModules *NativeEnumModules::clone() const {
-  return new NativeEnumModules(Session, Modules, Index);
+  return new NativeEnumModules(Session, Index);
 }
 
 }
index 38d6591..5dbdff7 100644 (file)
@@ -21,7 +21,7 @@ using namespace llvm::pdb;
 
 NativeEnumSymbol::NativeEnumSymbol(NativeSession &Session, SymIndexId Id,
                                    const codeview::CVType &CVT)
-    : NativeRawSymbol(Session, Id), CV(CVT),
+    : NativeRawSymbol(Session, PDB_SymType::Enum, Id), CV(CVT),
       Record(codeview::TypeRecordKind::Enum) {
   assert(CV.kind() == codeview::TypeLeafKind::LF_ENUM);
   cantFail(visitTypeRecord(CV, *this));
index e8b0606..3530570 100644 (file)
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
 
-namespace llvm {
-namespace pdb {
+using namespace llvm;
+using namespace llvm::pdb;
 
 NativeExeSymbol::NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId)
-    : NativeRawSymbol(Session, SymbolId), File(Session.getPDBFile()) {}
+    : NativeRawSymbol(Session, PDB_SymType::Exe, SymbolId),
+      File(Session.getPDBFile()) {
+  Expected<DbiStream &> DbiS = File.getPDBDbiStream();
+  if (!DbiS) {
+    consumeError(DbiS.takeError());
+    return;
+  }
+  Dbi = &DbiS.get();
+  Compilands.resize(Dbi->modules().getModuleCount());
+}
 
 std::unique_ptr<NativeRawSymbol> NativeExeSymbol::clone() const {
   return llvm::make_unique<NativeExeSymbol>(Session, SymbolId);
@@ -29,13 +40,7 @@ std::unique_ptr<IPDBEnumSymbols>
 NativeExeSymbol::findChildren(PDB_SymType Type) const {
   switch (Type) {
   case PDB_SymType::Compiland: {
-    auto Dbi = File.getPDBDbiStream();
-    if (Dbi) {
-      const DbiModuleList &Modules = Dbi->modules();
-      return std::unique_ptr<IPDBEnumSymbols>(
-          new NativeEnumModules(Session, Modules));
-    }
-    consumeError(Dbi.takeError());
+    return std::unique_ptr<IPDBEnumSymbols>(new NativeEnumModules(Session));
     break;
   }
   case PDB_SymType::Enum:
@@ -82,5 +87,26 @@ bool NativeExeSymbol::hasPrivateSymbols() const {
   return false;
 }
 
-} // namespace pdb
-} // namespace llvm
+uint32_t NativeExeSymbol::getNumCompilands() const {
+  if (!Dbi)
+    return 0;
+
+  return Dbi->modules().getModuleCount();
+}
+
+std::unique_ptr<PDBSymbolCompiland>
+NativeExeSymbol::getOrCreateCompiland(uint32_t Index) {
+  if (!Dbi)
+    return nullptr;
+
+  if (Index >= Compilands.size())
+    return nullptr;
+
+  if (Compilands[Index] == 0) {
+    const DbiModuleList &Modules = Dbi->modules();
+    Compilands[Index] = Session.createSymbol<NativeCompilandSymbol>(
+        Modules.getModuleDescriptor(Index));
+  }
+
+  return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
+}
index fbe3348..2152710 100644 (file)
@@ -14,8 +14,9 @@
 using namespace llvm;
 using namespace llvm::pdb;
 
-NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession, SymIndexId SymbolId)
-    : Session(PDBSession), SymbolId(SymbolId) {}
+NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession, PDB_SymType Tag,
+                                 SymIndexId SymbolId)
+    : Session(PDBSession), Tag(Tag), SymbolId(SymbolId) {}
 
 void NativeRawSymbol::dump(raw_ostream &OS, int Indent) const {}
 
@@ -374,9 +375,7 @@ PDB_DataKind NativeRawSymbol::getDataKind() const {
   return PDB_DataKind::Unknown;
 }
 
-PDB_SymType NativeRawSymbol::getSymTag() const {
-  return PDB_SymType::None;
-}
+PDB_SymType NativeRawSymbol::getSymTag() const { return Tag; }
 
 codeview::GUID NativeRawSymbol::getGuid() const { return codeview::GUID{{0}}; }
 
index bf66f1c..f3de408 100644 (file)
@@ -63,7 +63,10 @@ static const struct BuiltinTypeEntry {
 
 NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
                              std::unique_ptr<BumpPtrAllocator> Allocator)
-    : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {}
+    : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {
+  // Id 0 is reserved for the invalid symbol.
+  SymbolCache.push_back(nullptr);
+}
 
 NativeSession::~NativeSession() = default;
 
@@ -91,20 +94,10 @@ Error NativeSession::createFromExe(StringRef Path,
   return make_error<RawError>(raw_error_code::feature_unsupported);
 }
 
-std::unique_ptr<PDBSymbolCompiland>
-NativeSession::createCompilandSymbol(DbiModuleDescriptor MI) {
-  const auto Id = static_cast<SymIndexId>(SymbolCache.size());
-  SymbolCache.push_back(
-      llvm::make_unique<NativeCompilandSymbol>(*this, Id, MI));
-  return llvm::make_unique<PDBSymbolCompiland>(
-      *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
-}
-
 std::unique_ptr<PDBSymbolTypeEnum>
 NativeSession::createEnumSymbol(codeview::TypeIndex Index) {
   const auto Id = findSymbolByTypeIndex(Index);
-  return llvm::make_unique<PDBSymbolTypeEnum>(
-      *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
+  return PDBSymbol::createAs<PDBSymbolTypeEnum>(*this, *SymbolCache[Id]);
 }
 
 std::unique_ptr<IPDBEnumSymbols>
@@ -167,20 +160,14 @@ uint64_t NativeSession::getLoadAddress() const { return 0; }
 bool NativeSession::setLoadAddress(uint64_t Address) { return false; }
 
 std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
-  const auto Id = static_cast<SymIndexId>(SymbolCache.size());
-  SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, Id));
-  auto RawSymbol = SymbolCache[Id]->clone();
-  auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
-  std::unique_ptr<PDBSymbolExe> ExeSymbol(
-      static_cast<PDBSymbolExe *>(PdbSymbol.release()));
-  return ExeSymbol;
+  return PDBSymbol::createAs<PDBSymbolExe>(*this, getNativeGlobalScope());
 }
 
 std::unique_ptr<PDBSymbol>
 NativeSession::getSymbolById(uint32_t SymbolId) const {
   // If the caller has a SymbolId, it'd better be in our SymbolCache.
   return SymbolId < SymbolCache.size()
-             ? PDBSymbol::create(*this, SymbolCache[SymbolId]->clone())
+             ? PDBSymbol::create(*this, *SymbolCache[SymbolId])
              : nullptr;
 }
 
@@ -290,3 +277,11 @@ std::unique_ptr<IPDBEnumSectionContribs>
 NativeSession::getSectionContribs() const {
   return nullptr;
 }
+
+NativeExeSymbol &NativeSession::getNativeGlobalScope() {
+  if (ExeSymbol == 0) {
+    ExeSymbol = static_cast<SymIndexId>(SymbolCache.size());
+    SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, ExeSymbol));
+  }
+  return static_cast<NativeExeSymbol &>(*SymbolCache[ExeSymbol]);
+}
index 74010c2..df6eb73 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbol::PDBSymbol(const IPDBSession &PDBSession,
-                     std::unique_ptr<IPDBRawSymbol> Symbol)
-    : Session(PDBSession), RawSymbol(std::move(Symbol)) {}
+PDBSymbol::PDBSymbol(const IPDBSession &PDBSession) : Session(PDBSession) {}
 
-PDBSymbol::PDBSymbol(PDBSymbol &Symbol)
-    : Session(Symbol.Session), RawSymbol(std::move(Symbol.RawSymbol)) {}
+PDBSymbol::PDBSymbol(PDBSymbol &&Other)
+    : Session(Other.Session), RawSymbol(std::move(Other.RawSymbol)) {}
 
 PDBSymbol::~PDBSymbol() = default;
 
 #define FACTORY_SYMTAG_CASE(Tag, Type)                                         \
   case PDB_SymType::Tag:                                                       \
-    return std::unique_ptr<PDBSymbol>(new Type(PDBSession, std::move(Symbol)));
+    return std::unique_ptr<PDBSymbol>(new Type(PDBSession));
 
 std::unique_ptr<PDBSymbol>
-PDBSymbol::create(const IPDBSession &PDBSession,
-                  std::unique_ptr<IPDBRawSymbol> Symbol) {
-  switch (Symbol->getSymTag()) {
+PDBSymbol::createSymbol(const IPDBSession &PDBSession, PDB_SymType Tag) {
+  switch (Tag) {
     FACTORY_SYMTAG_CASE(Exe, PDBSymbolExe)
     FACTORY_SYMTAG_CASE(Compiland, PDBSymbolCompiland)
     FACTORY_SYMTAG_CASE(CompilandDetails, PDBSymbolCompilandDetails)
@@ -98,11 +95,26 @@ PDBSymbol::create(const IPDBSession &PDBSession,
     FACTORY_SYMTAG_CASE(ManagedType, PDBSymbolTypeManaged)
     FACTORY_SYMTAG_CASE(Dimension, PDBSymbolTypeDimension)
   default:
-    return std::unique_ptr<PDBSymbol>(
-        new PDBSymbolUnknown(PDBSession, std::move(Symbol)));
+    return std::unique_ptr<PDBSymbol>(new PDBSymbolUnknown(PDBSession));
   }
 }
 
+std::unique_ptr<PDBSymbol>
+PDBSymbol::create(const IPDBSession &PDBSession,
+                  std::unique_ptr<IPDBRawSymbol> RawSymbol) {
+  auto SymbolPtr = createSymbol(PDBSession, RawSymbol->getSymTag());
+  SymbolPtr->RawSymbol = RawSymbol.get();
+  SymbolPtr->OwnedRawSymbol = std::move(RawSymbol);
+  return std::move(SymbolPtr);
+}
+
+std::unique_ptr<PDBSymbol> PDBSymbol::create(const IPDBSession &PDBSession,
+                                             IPDBRawSymbol &RawSymbol) {
+  auto SymbolPtr = createSymbol(PDBSession, RawSymbol.getSymTag());
+  SymbolPtr->RawSymbol = &RawSymbol;
+  return std::move(SymbolPtr);
+}
+
 void PDBSymbol::defaultDump(raw_ostream &OS, int Indent) const {
   RawSymbol->dump(OS, Indent);
 }
index 3648272..cb1a9be 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolAnnotation::PDBSymbolAnnotation(const IPDBSession &PDBSession,
-                                         std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Annotation);
-}
-
 void PDBSymbolAnnotation::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index 7076b4a..13eec97 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolBlock::PDBSymbolBlock(const IPDBSession &PDBSession,
-                               std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Block);
-}
-
 void PDBSymbolBlock::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
index 8798c7b..bbc5e6d 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolCompiland::PDBSymbolCompiland(const IPDBSession &PDBSession,
-                                       std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Compiland);
-}
-
 void PDBSymbolCompiland::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index f73cd36..bdd8535 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolCompilandDetails::PDBSymbolCompilandDetails(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::CompilandDetails);
-}
-
 void PDBSymbolCompilandDetails::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index df696fa..f88df2d 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolCompilandEnv::PDBSymbolCompilandEnv(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::CompilandEnv);
-}
-
 std::string PDBSymbolCompilandEnv::getValue() const {
   Variant Value = RawSymbol->getValue();
   if (Value.Type != PDB_VariantType::String)
index a7b69a7..10a2180 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolCustom::PDBSymbolCustom(const IPDBSession &PDBSession,
-                                 std::unique_ptr<IPDBRawSymbol> CustomSymbol)
-    : PDBSymbol(PDBSession, std::move(CustomSymbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Custom);
-}
-
 void PDBSymbolCustom::getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) {
   RawSymbol->getDataBytes(bytes);
 }
index ae4a803..7de9467 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolData::PDBSymbolData(const IPDBSession &PDBSession,
-                             std::unique_ptr<IPDBRawSymbol> DataSymbol)
-    : PDBSymbol(PDBSession, std::move(DataSymbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Data);
-}
-
 void PDBSymbolData::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
 
 std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolData::getLineNumbers() const {
index 7417167..eb40941 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolExe::PDBSymbolExe(const IPDBSession &PDBSession,
-                           std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Exe);
-}
-
 void PDBSymbolExe::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
 
 uint32_t PDBSymbolExe::getPointerByteSize() const {
index 37ca1ab..c810e4e 100644 (file)
@@ -82,12 +82,6 @@ private:
 };
 }
 
-PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession,
-                             std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Function);
-}
-
 std::unique_ptr<IPDBEnumChildren<PDBSymbolData>>
 PDBSymbolFunc::getArguments() const {
   return llvm::make_unique<FunctionArgEnumerator>(Session, *this);
index 4a4195b..af8aafa 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolFuncDebugEnd::PDBSymbolFuncDebugEnd(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::FuncDebugEnd);
-}
-
 void PDBSymbolFuncDebugEnd::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index a448a40..77b5108 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolFuncDebugStart::PDBSymbolFuncDebugStart(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::FuncDebugStart);
-}
-
 void PDBSymbolFuncDebugStart::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index a67a20d..c802b97 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolLabel::PDBSymbolLabel(const IPDBSession &PDBSession,
-                               std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Label);
-}
-
 void PDBSymbolLabel::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
index dbec16f..a2dd2ab 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolPublicSymbol::PDBSymbolPublicSymbol(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::PublicSymbol);
-}
-
 void PDBSymbolPublicSymbol::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index b264819..d227e3a 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolThunk::PDBSymbolThunk(const IPDBSession &PDBSession,
-                               std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Thunk);
-}
-
 void PDBSymbolThunk::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
index ba40f65..a2064d1 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeArray::PDBSymbolTypeArray(const IPDBSession &PDBSession,
-                                       std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::ArrayType);
-}
-
 void PDBSymbolTypeArray::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index 0fdf8b6..f0376c0 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeBaseClass::PDBSymbolTypeBaseClass(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::BaseClass);
-}
-
 void PDBSymbolTypeBaseClass::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index 0bf563a..a9f59e5 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeBuiltin::PDBSymbolTypeBuiltin(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::BuiltinType);
-}
-
 void PDBSymbolTypeBuiltin::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index 726e7e1..cfb347f 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeCustom::PDBSymbolTypeCustom(const IPDBSession &PDBSession,
-                                         std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::CustomType);
-}
-
 void PDBSymbolTypeCustom::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index 6c84b98..4eb4899 100644 (file)
 
 using namespace llvm;
 using namespace llvm::pdb;
-
-PDBSymbolTypeDimension::PDBSymbolTypeDimension(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Dimension);
-}
-
 void PDBSymbolTypeDimension::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index f9c3067..2e88d9e 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeEnum::PDBSymbolTypeEnum(const IPDBSession &PDBSession,
-                                     std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Enum);
-}
-
 void PDBSymbolTypeEnum::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
index c018772..00d2d51 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeFriend::PDBSymbolTypeFriend(const IPDBSession &PDBSession,
-                                         std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Friend);
-}
-
 void PDBSymbolTypeFriend::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index 4d5cd63..0399e11 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeFunctionArg::PDBSymbolTypeFunctionArg(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::FunctionArg);
-}
-
 void PDBSymbolTypeFunctionArg::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index 8fd3b49..c6148a3 100644 (file)
@@ -67,12 +67,6 @@ private:
 };
 }
 
-PDBSymbolTypeFunctionSig::PDBSymbolTypeFunctionSig(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::FunctionSig);
-}
-
 std::unique_ptr<IPDBEnumSymbols>
 PDBSymbolTypeFunctionSig::getArguments() const {
   return llvm::make_unique<FunctionArgEnumerator>(Session, *this);
index 7cfba82..1faaf9c 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeManaged::PDBSymbolTypeManaged(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::ManagedType);
-}
-
 void PDBSymbolTypeManaged::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index 6981981..cf5a369 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypePointer::PDBSymbolTypePointer(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::PointerType);
-}
-
 void PDBSymbolTypePointer::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index 102b540..1838f16 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeTypedef::PDBSymbolTypeTypedef(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::Typedef);
-}
-
 void PDBSymbolTypeTypedef::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index 715ae15..2f5222f 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeUDT::PDBSymbolTypeUDT(const IPDBSession &PDBSession,
-                                   std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::UDT);
-}
-
 void PDBSymbolTypeUDT::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
index 9a21855..0262f91 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeVTable::PDBSymbolTypeVTable(const IPDBSession &PDBSession,
-                                         std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::VTable);
-}
-
 void PDBSymbolTypeVTable::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index ddc0574..16c3a36 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolTypeVTableShape::PDBSymbolTypeVTableShape(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::VTableShape);
-}
-
 void PDBSymbolTypeVTableShape::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index fdbe845..7bcf945 100644 (file)
@@ -17,8 +17,4 @@
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolUnknown::PDBSymbolUnknown(const IPDBSession &PDBSession,
-                                   std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {}
-
 void PDBSymbolUnknown::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
index f40578f..ecf2126 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-PDBSymbolUsingNamespace::PDBSymbolUsingNamespace(
-    const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
-    : PDBSymbol(PDBSession, std::move(Symbol)) {
-  assert(RawSymbol->getSymTag() == PDB_SymType::UsingNamespace);
-}
-
 void PDBSymbolUsingNamespace::dump(PDBSymDumper &Dumper) const {
   Dumper.dump(*this);
 }
index e07ded9..bd77ee0 100644 (file)
@@ -1054,7 +1054,9 @@ static void dumpPretty(StringRef Path) {
     Printer.NewLine();
     WithColor(Printer, PDB_ColorItem::SectionHeader).get()
         << "---COMPILANDS---";
-    if (auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>()) {
+    auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
+
+    if (Compilands) {
       Printer.Indent();
       CompilandDumper Dumper(Printer);
       CompilandDumpFlags options = CompilandDumper::Flags::None;
index 5410e5f..842a42b 100644 (file)
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_unittest(DebugInfoPDBTests
   HashTableTest.cpp
+  NativeSymbolReuseTest.cpp
   StringTableBuilderTest.cpp
   PDBApiTest.cpp
   )
diff --git a/unittests/DebugInfo/PDB/Inputs/empty.pdb b/unittests/DebugInfo/PDB/Inputs/empty.pdb
new file mode 100644 (file)
index 0000000..ae65c3a
Binary files /dev/null and b/unittests/DebugInfo/PDB/Inputs/empty.pdb differ
diff --git a/unittests/DebugInfo/PDB/NativeSymbolReuseTest.cpp b/unittests/DebugInfo/PDB/NativeSymbolReuseTest.cpp
new file mode 100644 (file)
index 0000000..8c98f83
--- /dev/null
@@ -0,0 +1,128 @@
+//===- NativeSymbolReuseTest.cpp ------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDB.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/Support/Path.h"
+
+#include "llvm/Testing/Support/Error.h"
+#include "llvm/Testing/Support/SupportHelpers.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+TEST(NativeSymbolReuseTest, GlobalSymbolReuse) {
+  SmallString<128> InputsDir = unittest::getInputFileDirectory();
+  llvm::sys::path::append(InputsDir, "empty.pdb");
+
+  std::unique_ptr<IPDBSession> S;
+  Error E = pdb::loadDataForPDB(PDB_ReaderType::Native, InputsDir, S);
+
+  ASSERT_THAT_ERROR(std::move(E), Succeeded());
+
+  SymIndexId GlobalId;
+  {
+    auto GS1 = S->getGlobalScope();
+    auto GS2 = S->getGlobalScope();
+
+    GlobalId = GS1->getSymIndexId();
+    SymIndexId Id2 = GS1->getSymIndexId();
+    EXPECT_EQ(GlobalId, Id2);
+  }
+
+  {
+    auto GS3 = S->getGlobalScope();
+
+    SymIndexId Id3 = GS3->getSymIndexId();
+    EXPECT_EQ(GlobalId, Id3);
+  }
+}
+
+TEST(NativeSymbolReuseTest, CompilandSymbolReuse) {
+  SmallString<128> InputsDir = unittest::getInputFileDirectory();
+  llvm::sys::path::append(InputsDir, "empty.pdb");
+
+  std::unique_ptr<IPDBSession> S;
+  Error E = pdb::loadDataForPDB(PDB_ReaderType::Native, InputsDir, S);
+
+  ASSERT_THAT_ERROR(std::move(E), Succeeded());
+
+  auto GS = S->getGlobalScope();
+
+  std::vector<SymIndexId> CompilandIds;
+  {
+    auto Compilands = GS->findAllChildren<PDBSymbolCompiland>();
+    ASSERT_NE(nullptr, Compilands);
+    ASSERT_EQ(2, Compilands->getChildCount());
+    std::vector<SymIndexId> Ids2;
+
+    // First try resetting the enumerator, then try destroying the enumerator
+    // and constructing another one.
+    while (auto Compiland = Compilands->getNext())
+      CompilandIds.push_back(Compiland->getSymIndexId());
+    Compilands->reset();
+    while (auto Compiland = Compilands->getNext())
+      Ids2.push_back(Compiland->getSymIndexId());
+
+    EXPECT_EQ(CompilandIds, Ids2);
+  }
+
+  {
+    auto Compilands = GS->findAllChildren<PDBSymbolCompiland>();
+    ASSERT_NE(nullptr, Compilands);
+    ASSERT_EQ(2U, Compilands->getChildCount());
+
+    std::vector<SymIndexId> Ids3;
+    while (auto Compiland = Compilands->getNext())
+      Ids3.push_back(Compiland->getSymIndexId());
+
+    EXPECT_EQ(CompilandIds, Ids3);
+  }
+}
+
+TEST(NativeSymbolReuseTest, CompilandSymbolReuseBackwards) {
+  SmallString<128> InputsDir = unittest::getInputFileDirectory();
+  llvm::sys::path::append(InputsDir, "empty.pdb");
+
+  std::unique_ptr<IPDBSession> S;
+  Error E = pdb::loadDataForPDB(PDB_ReaderType::Native, InputsDir, S);
+
+  ASSERT_THAT_ERROR(std::move(E), Succeeded());
+
+  auto GS = S->getGlobalScope();
+
+  // This time do the first iteration backwards, and make sure that when you
+  // then iterate them forwards, the IDs come out in reverse.
+  std::vector<SymIndexId> CompilandIds;
+  {
+    auto Compilands = GS->findAllChildren<PDBSymbolCompiland>();
+    ASSERT_NE(nullptr, Compilands);
+    ASSERT_EQ(2U, Compilands->getChildCount());
+
+    std::vector<SymIndexId> Ids2;
+
+    for (int I = Compilands->getChildCount() - 1; I >= 0; --I) {
+      auto Compiland = Compilands->getChildAtIndex(I);
+      CompilandIds.push_back(Compiland->getSymIndexId());
+    }
+
+    while (auto Compiland = Compilands->getNext())
+      Ids2.push_back(Compiland->getSymIndexId());
+
+    auto ReversedIter = llvm::reverse(Ids2);
+    std::vector<SymIndexId> Reversed{ReversedIter.begin(), ReversedIter.end()};
+    EXPECT_EQ(CompilandIds, Reversed);
+  }
+}