[llvm] r342779 - [PDB] Add native reading support for UDT / class types.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 21 15:36:05 PDT 2018


Author: zturner
Date: Fri Sep 21 15:36:04 2018
New Revision: 342779

URL: http://llvm.org/viewvc/llvm-project?rev=342779&view=rev
Log:
[PDB] Add native reading support for UDT / class types.

This allows the native reader to find records of class/struct/
union type and dump them.  This behavior is tested by using the
diadump subcommand against golden output produced by actual DIA
SDK on the same PDB file, and again using pretty -native to
confirm that we actually dump the classes.  We don't find class
members or anything like that yet, for now it's just the class
itself.

Added:
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h
    llvm/trunk/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
    llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-udts.test
Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h
    llvm/trunk/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
    llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
    llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt
    llvm/trunk/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/SymbolCache.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp
    llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h Fri Sep 21 15:36:04 2018
@@ -923,6 +923,7 @@ public:
 
   uint32_t Signature;
 };
+
 } // end namespace codeview
 } // end namespace llvm
 

Added: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h?rev=342779&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h Fri Sep 21 15:36:04 2018
@@ -0,0 +1,28 @@
+//===- TypeRecordHelpers.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H
+
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+
+namespace llvm {
+  namespace codeview {
+    /// Given an arbitrary codeview type, determine if it is an LF_STRUCTURE,
+    /// LF_CLASS, LF_INTERFACE, LF_UNION, or LF_ENUM with the forward ref class
+    /// option.
+    bool isUdtForwardRef(CVType CVT);
+
+    /// Given a CVType which is assumed to be an LF_MODIFIER, return the
+    /// TypeIndex of the type that the LF_MODIFIER modifies.
+    TypeIndex getModifiedType(const CVType &CVT);
+  }
+}
+
+#endif

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h Fri Sep 21 15:36:04 2018
@@ -35,11 +35,9 @@ class NullEnumerator : public IPDBEnumCh
   virtual uint32_t getChildCount() const override { return 0; }
   virtual std::unique_ptr<ChildType>
   getChildAtIndex(uint32_t Index) const override {
-    assert(false);
     return nullptr;
   }
   virtual std::unique_ptr<ChildType> getNext() override {
-    assert(false);
     return nullptr;
   }
   virtual void reset() override {}

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h Fri Sep 21 15:36:04 2018
@@ -26,7 +26,7 @@ class NativeEnumTypes : public IPDBEnumC
 public:
   NativeEnumTypes(NativeSession &Session,
                   codeview::LazyRandomTypeCollection &TypeCollection,
-                  codeview::TypeLeafKind Kind);
+                  std::vector<codeview::TypeLeafKind> Kinds);
 
   uint32_t getChildCount() const override;
   std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
@@ -34,10 +34,6 @@ public:
   void reset() override;
 
 private:
-  NativeEnumTypes(NativeSession &Session,
-                  const std::vector<codeview::TypeIndex> &Matches,
-                  codeview::TypeLeafKind Kind);
-
   std::vector<codeview::TypeIndex> Matches;
   uint32_t Index;
   NativeSession &Session;

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h Fri Sep 21 15:36:04 2018
@@ -10,6 +10,7 @@
 #ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H
 #define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H
 
+#include "llvm/ADT/Optional.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
@@ -26,9 +27,8 @@ public:
                  codeview::EnumRecord Record);
 
   NativeTypeEnum(NativeSession &Session, SymIndexId Id,
-                 codeview::TypeIndex ModifierTI,
-                 codeview::ModifierRecord Modifier,
-                 codeview::EnumRecord EnumRecord);
+                 NativeTypeEnum &UnmodifiedType,
+                 codeview::ModifierRecord Modifier);
   ~NativeTypeEnum() override;
 
   void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
@@ -60,10 +60,12 @@ public:
   bool isInterfaceUdt() const override;
 
   const NativeTypeBuiltin &getUnderlyingBuiltinType() const;
+  const codeview::EnumRecord &getEnumRecord() const { return *Record; }
 
 protected:
   codeview::TypeIndex Index;
-  codeview::EnumRecord Record;
+  Optional<codeview::EnumRecord> Record;
+  NativeTypeEnum *UnmodifiedType = nullptr;
   Optional<codeview::ModifierRecord> Modifiers;
 };
 

Added: llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h?rev=342779&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h Fri Sep 21 15:36:04 2018
@@ -0,0 +1,74 @@
+//===- NativeTypeUDT.h - info about class/struct type ------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativeTypeUDT : public NativeRawSymbol {
+public:
+  NativeTypeUDT(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI,
+                codeview::ClassRecord Class);
+
+  NativeTypeUDT(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI,
+                codeview::UnionRecord Union);
+
+  NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+                NativeTypeUDT &UnmodifiedType,
+                codeview::ModifierRecord Modifier);
+
+  ~NativeTypeUDT() override;
+
+  void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+            PdbSymbolIdField RecurseIdFields) const override;
+
+  std::string getName() const override;
+  SymIndexId getLexicalParentId() const override;
+  SymIndexId getUnmodifiedTypeId() const override;
+  SymIndexId getVirtualTableShapeId() const override;
+  uint64_t getLength() const override;
+  PDB_UdtType getUdtKind() const override;
+  bool hasConstructor() const override;
+  bool isConstType() const override;
+  bool hasAssignmentOperator() const override;
+  bool hasCastOperator() const override;
+  bool hasNestedTypes() const override;
+  bool hasOverloadedOperator() const override;
+  bool isInterfaceUdt() const override;
+  bool isIntrinsic() const override;
+  bool isNested() const override;
+  bool isPacked() const override;
+  bool isRefUdt() const override;
+  bool isScoped() const override;
+  bool isValueUdt() const override;
+  bool isUnalignedType() const override;
+  bool isVolatileType() const override;
+
+protected:
+  codeview::TypeIndex Index;
+
+  Optional<codeview::ClassRecord> Class;
+  Optional<codeview::UnionRecord> Union;
+  NativeTypeUDT *UnmodifiedType = nullptr;
+  codeview::TagRecord *Tag = nullptr;
+  Optional<codeview::ModifierRecord> Modifiers;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H
\ No newline at end of file

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/SymbolCache.h?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/SymbolCache.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/SymbolCache.h Fri Sep 21 15:36:04 2018
@@ -77,6 +77,9 @@ public:
   std::unique_ptr<IPDBEnumSymbols>
   createTypeEnumerator(codeview::TypeLeafKind Kind);
 
+  std::unique_ptr<IPDBEnumSymbols>
+  createTypeEnumerator(std::vector<codeview::TypeLeafKind> Kinds);
+
   SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
 
   template <typename ConcreteSymbolT, typename... Args>

Modified: llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt Fri Sep 21 15:36:04 2018
@@ -34,6 +34,7 @@ add_llvm_library(LLVMDebugInfoCodeView
   TypeIndex.cpp
   TypeIndexDiscovery.cpp
   TypeHashing.cpp
+  TypeRecordHelpers.cpp
   TypeRecordMapping.cpp
   TypeStreamMerger.cpp
   TypeTableCollection.cpp

Added: llvm/trunk/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp?rev=342779&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp (added)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp Fri Sep 21 15:36:04 2018
@@ -0,0 +1,53 @@
+//===- TypeRecordHelpers.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) {
+  RecordT Record;
+  if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) {
+    consumeError(std::move(EC));
+    return ClassOptions::None;
+  }
+  return Record.getOptions();
+}
+
+bool llvm::codeview::isUdtForwardRef(CVType CVT) {
+  ClassOptions UdtOptions = ClassOptions::None;
+  switch (CVT.kind()) {
+  case LF_STRUCTURE:
+  case LF_CLASS:
+  case LF_INTERFACE:
+    UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT));
+    break;
+  case LF_ENUM:
+    UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT));
+    break;
+  case LF_UNION:
+    UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT));
+    break;
+  default:
+    return false;
+  }
+  return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None;
+}
+
+TypeIndex llvm::codeview::getModifiedType(const CVType &CVT) {
+  assert(CVT.kind() == LF_MODIFIER);
+  SmallVector<TypeIndex, 1> Refs;
+  discoverTypeIndices(CVT, Refs);
+  return Refs.front();
+}

Modified: llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt Fri Sep 21 15:36:04 2018
@@ -55,6 +55,7 @@ add_pdb_impl_folder(Native
   Native/NativeTypeBuiltin.cpp
   Native/NativeTypeEnum.cpp
   Native/NativeTypePointer.cpp
+  Native/NativeTypeUDT.cpp
   Native/NamedStreamMap.cpp
   Native/NativeSession.cpp
   Native/PDBFile.cpp

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp Fri Sep 21 15:36:04 2018
@@ -10,6 +10,7 @@
 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
 
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
 #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
@@ -22,21 +23,24 @@ using namespace llvm::pdb;
 
 NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
                                  LazyRandomTypeCollection &Types,
-                                 TypeLeafKind Kind)
+                                 std::vector<codeview::TypeLeafKind> Kinds)
     : Matches(), Index(0), Session(PDBSession) {
   Optional<TypeIndex> TI = Types.getFirst();
   while (TI) {
     CVType CVT = Types.getType(*TI);
     TypeLeafKind K = CVT.kind();
-    if (K == Kind)
-      Matches.push_back(*TI);
-    else if (K == TypeLeafKind::LF_MODIFIER) {
-      ModifierRecord MR;
-      if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, MR)) {
-        consumeError(std::move(EC));
-      } else if (!MR.ModifiedType.isSimple()) {
-        CVType UnmodifiedCVT = Types.getType(MR.ModifiedType);
-        if (UnmodifiedCVT.kind() == Kind)
+    if (llvm::is_contained(Kinds, K)) {
+      // Don't add forward refs, we'll find those later while enumerating.
+      if (!isUdtForwardRef(CVT))
+        Matches.push_back(*TI);
+    } else if (K == TypeLeafKind::LF_MODIFIER) {
+      TypeIndex ModifiedTI = getModifiedType(CVT);
+      if (!ModifiedTI.isSimple()) {
+        CVType UnmodifiedCVT = Types.getType(ModifiedTI);
+        // LF_MODIFIERs point to forward refs, but don't worry about that
+        // here.  We're pushing the TypeIndex of the LF_MODIFIER itself,
+        // so we'll worry about resolving forward refs later.
+        if (llvm::is_contained(Kinds, UnmodifiedCVT.kind()))
           Matches.push_back(*TI);
       }
     }
@@ -44,11 +48,6 @@ NativeEnumTypes::NativeEnumTypes(NativeS
   }
 }
 
-NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
-                                 const std::vector<TypeIndex> &Matches,
-                                 TypeLeafKind Kind)
-    : Matches(Matches), Index(0), Session(PDBSession) {}
-
 uint32_t NativeEnumTypes::getChildCount() const {
   return static_cast<uint32_t>(Matches.size());
 }

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp Fri Sep 21 15:36:04 2018
@@ -45,6 +45,10 @@ NativeExeSymbol::findChildren(PDB_SymTyp
     return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ENUM);
   case PDB_SymType::PointerType:
     return Session.getSymbolCache().createTypeEnumerator(codeview::LF_POINTER);
+  case PDB_SymType::UDT:
+    return Session.getSymbolCache().createTypeEnumerator(
+        {codeview::LF_STRUCTURE, codeview::LF_CLASS, codeview::LF_UNION,
+         codeview::LF_INTERFACE});
   default:
     break;
   }

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp Fri Sep 21 15:36:04 2018
@@ -31,68 +31,68 @@ void NativeRawSymbol::dump(raw_ostream &
 
 std::unique_ptr<IPDBEnumSymbols>
 NativeRawSymbol::findChildren(PDB_SymType Type) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
 }
 
 std::unique_ptr<IPDBEnumSymbols>
 NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name,
     PDB_NameSearchFlags Flags) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
 }
 
 std::unique_ptr<IPDBEnumSymbols>
 NativeRawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name,
     PDB_NameSearchFlags Flags, uint32_t Section, uint32_t Offset) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
 }
 
 std::unique_ptr<IPDBEnumSymbols>
 NativeRawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name,
    PDB_NameSearchFlags Flags, uint64_t VA) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
 }
 
 std::unique_ptr<IPDBEnumSymbols>
 NativeRawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
     PDB_NameSearchFlags Flags, uint32_t RVA) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
 }
 
 std::unique_ptr<IPDBEnumSymbols>
 NativeRawSymbol::findInlineFramesByAddr(uint32_t Section,
                                         uint32_t Offset) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
 }
 
 std::unique_ptr<IPDBEnumSymbols>
 NativeRawSymbol::findInlineFramesByRVA(uint32_t RVA) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
 }
 
 std::unique_ptr<IPDBEnumSymbols>
 NativeRawSymbol::findInlineFramesByVA(uint64_t VA) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<PDBSymbol>>();
 }
 
 std::unique_ptr<IPDBEnumLineNumbers>
 NativeRawSymbol::findInlineeLines() const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
 }
 
 std::unique_ptr<IPDBEnumLineNumbers>
 NativeRawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset,
                                         uint32_t Length) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
 }
 
 std::unique_ptr<IPDBEnumLineNumbers>
 NativeRawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
 }
 
 std::unique_ptr<IPDBEnumLineNumbers>
 NativeRawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const {
-  return nullptr;
+  return llvm::make_unique<NullEnumerator<IPDBLineNumber>>();
 }
 
 void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const {

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp Fri Sep 21 15:36:04 2018
@@ -40,8 +40,7 @@ namespace {
 class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
 public:
   NativeEnumEnumEnumerators(NativeSession &Session,
-                            const NativeTypeEnum &ClassParent,
-                            const codeview::EnumRecord &CVEnum);
+                            const NativeTypeEnum &ClassParent);
 
   uint32_t getChildCount() const override;
   std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
@@ -56,7 +55,6 @@ private:
 
   NativeSession &Session;
   const NativeTypeEnum &ClassParent;
-  const codeview::EnumRecord &CVEnum;
   std::vector<EnumeratorRecord> Enumerators;
   Optional<TypeIndex> ContinuationIndex;
   uint32_t Index = 0;
@@ -64,13 +62,12 @@ private:
 } // namespace
 
 NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
-    NativeSession &Session, const NativeTypeEnum &ClassParent,
-    const codeview::EnumRecord &CVEnum)
-    : Session(Session), ClassParent(ClassParent), CVEnum(CVEnum) {
+    NativeSession &Session, const NativeTypeEnum &ClassParent)
+    : Session(Session), ClassParent(ClassParent) {
   TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
   LazyRandomTypeCollection &Types = Tpi.typeCollection();
 
-  ContinuationIndex = CVEnum.FieldList;
+  ContinuationIndex = ClassParent.getEnumRecord().FieldList;
   while (ContinuationIndex) {
     CVType FieldList = Types.getType(*ContinuationIndex);
     assert(FieldList.kind() == LF_FIELDLIST);
@@ -100,10 +97,10 @@ NativeEnumEnumEnumerators::getChildAtInd
   if (Index >= getChildCount())
     return nullptr;
 
-  SymIndexId Id =
-      Session.getSymbolCache()
-          .getOrCreateFieldListMember<NativeSymbolEnumerator>(
-              CVEnum.FieldList, Index, ClassParent, Enumerators[Index]);
+  SymIndexId Id = Session.getSymbolCache()
+                      .getOrCreateFieldListMember<NativeSymbolEnumerator>(
+                          ClassParent.getEnumRecord().FieldList, Index,
+                          ClassParent, Enumerators[Index]);
   return Session.getSymbolCache().getSymbolById(Id);
 }
 
@@ -122,11 +119,10 @@ NativeTypeEnum::NativeTypeEnum(NativeSes
       Record(std::move(Record)) {}
 
 NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
-                               codeview::TypeIndex ModifierTI,
-                               codeview::ModifierRecord Modifier,
-                               codeview::EnumRecord EnumRecord)
-    : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(ModifierTI),
-      Record(std::move(EnumRecord)), Modifiers(std::move(Modifier)) {}
+                               NativeTypeEnum &UnmodifiedType,
+                               codeview::ModifierRecord Modifier)
+    : NativeRawSymbol(Session, PDB_SymType::Enum, Id),
+      UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
 
 NativeTypeEnum::~NativeTypeEnum() {}
 
@@ -173,22 +169,20 @@ NativeTypeEnum::findChildren(PDB_SymType
   const NativeTypeEnum *ClassParent = nullptr;
   if (!Modifiers)
     ClassParent = this;
-  else {
-    NativeRawSymbol &NRS =
-        Session.getSymbolCache().getNativeSymbolById(getUnmodifiedTypeId());
-    assert(NRS.getSymTag() == PDB_SymType::Enum);
-    ClassParent = static_cast<NativeTypeEnum *>(&NRS);
-  }
-  return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent,
-                                                      Record);
+  else
+    ClassParent = UnmodifiedType;
+  return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent);
 }
 
 PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
 
 PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
-  Session.getSymbolCache().findSymbolByTypeIndex(Record.getUnderlyingType());
+  if (UnmodifiedType)
+    return UnmodifiedType->getBuiltinType();
+
+  Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType());
 
-  codeview::TypeIndex Underlying = Record.getUnderlyingType();
+  codeview::TypeIndex Underlying = Record->getUnderlyingType();
 
   // This indicates a corrupt record.
   if (!Underlying.isSimple() ||
@@ -255,67 +249,101 @@ PDB_BuiltinType NativeTypeEnum::getBuilt
 }
 
 SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
-  if (!Modifiers)
-    return 0;
-
-  return Session.getSymbolCache().findSymbolByTypeIndex(
-      Modifiers->ModifiedType);
+  return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0;
 }
 
 bool NativeTypeEnum::hasConstructor() const {
-  return bool(Record.getOptions() &
+  if (UnmodifiedType)
+    return UnmodifiedType->hasConstructor();
+
+  return bool(Record->getOptions() &
               codeview::ClassOptions::HasConstructorOrDestructor);
 }
 
 bool NativeTypeEnum::hasAssignmentOperator() const {
-  return bool(Record.getOptions() &
+  if (UnmodifiedType)
+    return UnmodifiedType->hasAssignmentOperator();
+
+  return bool(Record->getOptions() &
               codeview::ClassOptions::HasOverloadedAssignmentOperator);
 }
 
 bool NativeTypeEnum::hasNestedTypes() const {
-  return bool(Record.getOptions() &
+  if (UnmodifiedType)
+    return UnmodifiedType->hasNestedTypes();
+
+  return bool(Record->getOptions() &
               codeview::ClassOptions::ContainsNestedClass);
 }
 
 bool NativeTypeEnum::isIntrinsic() const {
-  return bool(Record.getOptions() & codeview::ClassOptions::Intrinsic);
+  if (UnmodifiedType)
+    return UnmodifiedType->isIntrinsic();
+
+  return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic);
 }
 
 bool NativeTypeEnum::hasCastOperator() const {
-  return bool(Record.getOptions() &
+  if (UnmodifiedType)
+    return UnmodifiedType->hasCastOperator();
+
+  return bool(Record->getOptions() &
               codeview::ClassOptions::HasConversionOperator);
 }
 
 uint64_t NativeTypeEnum::getLength() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getLength();
+
   const auto Id = Session.getSymbolCache().findSymbolByTypeIndex(
-      Record.getUnderlyingType());
+      Record->getUnderlyingType());
   const auto UnderlyingType =
       Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
   return UnderlyingType ? UnderlyingType->getLength() : 0;
 }
 
-std::string NativeTypeEnum::getName() const { return Record.getName(); }
+std::string NativeTypeEnum::getName() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getName();
+
+  return Record->getName();
+}
 
 bool NativeTypeEnum::isNested() const {
-  return bool(Record.getOptions() & codeview::ClassOptions::Nested);
+  if (UnmodifiedType)
+    return UnmodifiedType->isNested();
+
+  return bool(Record->getOptions() & codeview::ClassOptions::Nested);
 }
 
 bool NativeTypeEnum::hasOverloadedOperator() const {
-  return bool(Record.getOptions() &
+  if (UnmodifiedType)
+    return UnmodifiedType->hasOverloadedOperator();
+
+  return bool(Record->getOptions() &
               codeview::ClassOptions::HasOverloadedOperator);
 }
 
 bool NativeTypeEnum::isPacked() const {
-  return bool(Record.getOptions() & codeview::ClassOptions::Packed);
+  if (UnmodifiedType)
+    return UnmodifiedType->isPacked();
+
+  return bool(Record->getOptions() & codeview::ClassOptions::Packed);
 }
 
 bool NativeTypeEnum::isScoped() const {
-  return bool(Record.getOptions() & codeview::ClassOptions::Scoped);
+  if (UnmodifiedType)
+    return UnmodifiedType->isScoped();
+
+  return bool(Record->getOptions() & codeview::ClassOptions::Scoped);
 }
 
 SymIndexId NativeTypeEnum::getTypeId() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getTypeId();
+
   return Session.getSymbolCache().findSymbolByTypeIndex(
-      Record.getUnderlyingType());
+      Record->getUnderlyingType());
 }
 
 bool NativeTypeEnum::isRefUdt() const { return false; }
@@ -346,6 +374,9 @@ bool NativeTypeEnum::isUnalignedType() c
 }
 
 const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getUnderlyingBuiltinType();
+
   return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
       getTypeId());
 }

Added: llvm/trunk/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp?rev=342779&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp (added)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp Fri Sep 21 15:36:04 2018
@@ -0,0 +1,221 @@
+//===- NativeTypeUDT.cpp - info about class/struct type ---------*- C++ -*-===//
+//
+//                     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/Native/NativeTypeUDT.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+                             codeview::TypeIndex TI, codeview::ClassRecord CR)
+    : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI),
+      Class(std::move(CR)), Tag(Class.getPointer()) {}
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+                             codeview::TypeIndex TI, codeview::UnionRecord UR)
+    : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI),
+      Union(std::move(UR)), Tag(Union.getPointer()) {}
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+                             NativeTypeUDT &UnmodifiedType,
+                             codeview::ModifierRecord Modifier)
+    : NativeRawSymbol(Session, PDB_SymType::UDT, Id),
+      UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
+
+NativeTypeUDT::~NativeTypeUDT() {}
+
+void NativeTypeUDT::dump(raw_ostream &OS, int Indent,
+                         PdbSymbolIdField ShowIdFields,
+                         PdbSymbolIdField RecurseIdFields) const {
+
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+  dumpSymbolField(OS, "name", getName(), Indent);
+  dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+                    PdbSymbolIdField::LexicalParent, ShowIdFields,
+                    RecurseIdFields);
+  if (Modifiers.hasValue())
+    dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
+                      Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
+                      RecurseIdFields);
+  if (getUdtKind() != PDB_UdtType::Union)
+    dumpSymbolField(OS, "virtualTableShapeId", getVirtualTableShapeId(),
+                    Indent);
+  dumpSymbolField(OS, "length", getLength(), Indent);
+  dumpSymbolField(OS, "udtKind", getUdtKind(), Indent);
+  dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
+  dumpSymbolField(OS, "constType", isConstType(), Indent);
+  dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
+  dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
+  dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
+  dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
+  dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
+  dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
+  dumpSymbolField(OS, "nested", isNested(), Indent);
+  dumpSymbolField(OS, "packed", isPacked(), Indent);
+  dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
+  dumpSymbolField(OS, "scoped", isScoped(), Indent);
+  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+  dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
+  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+std::string NativeTypeUDT::getName() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getName();
+
+  return Tag->getName();
+}
+
+SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; }
+
+SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getSymIndexId();
+
+  return 0;
+}
+
+SymIndexId NativeTypeUDT::getVirtualTableShapeId() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getVirtualTableShapeId();
+
+  if (Class)
+    return Session.getSymbolCache().findSymbolByTypeIndex(Class->VTableShape);
+
+  return 0;
+}
+
+uint64_t NativeTypeUDT::getLength() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getLength();
+
+  if (Class)
+    return Class->getSize();
+
+  return Union->getSize();
+}
+
+PDB_UdtType NativeTypeUDT::getUdtKind() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->getUdtKind();
+
+  switch (Tag->Kind) {
+  case TypeRecordKind::Class:
+    return PDB_UdtType::Class;
+  case TypeRecordKind::Union:
+    return PDB_UdtType::Union;
+  case TypeRecordKind::Struct:
+    return PDB_UdtType::Struct;
+  case TypeRecordKind::Interface:
+    return PDB_UdtType::Interface;
+  default:
+    llvm_unreachable("Unexected udt kind");
+  }
+}
+
+bool NativeTypeUDT::hasConstructor() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasConstructor();
+
+  return (Tag->Options & ClassOptions::HasConstructorOrDestructor) !=
+         ClassOptions::None;
+}
+
+bool NativeTypeUDT::isConstType() const {
+  if (!Modifiers)
+    return false;
+  return (Modifiers->Modifiers & ModifierOptions::Const) !=
+         ModifierOptions::None;
+}
+
+bool NativeTypeUDT::hasAssignmentOperator() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasAssignmentOperator();
+
+  return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) !=
+         ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasCastOperator() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasCastOperator();
+
+  return (Tag->Options & ClassOptions::HasConversionOperator) !=
+         ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasNestedTypes() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasNestedTypes();
+
+  return (Tag->Options & ClassOptions::ContainsNestedClass) !=
+         ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasOverloadedOperator() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->hasOverloadedOperator();
+
+  return (Tag->Options & ClassOptions::HasOverloadedOperator) !=
+         ClassOptions::None;
+}
+
+bool NativeTypeUDT::isInterfaceUdt() const { return false; }
+
+bool NativeTypeUDT::isIntrinsic() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isIntrinsic();
+
+  return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isNested() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isNested();
+
+  return (Tag->Options & ClassOptions::Nested) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isPacked() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isPacked();
+
+  return (Tag->Options & ClassOptions::Packed) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isRefUdt() const { return false; }
+
+bool NativeTypeUDT::isScoped() const {
+  if (UnmodifiedType)
+    return UnmodifiedType->isScoped();
+
+  return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isValueUdt() const { return false; }
+
+bool NativeTypeUDT::isUnalignedType() const {
+  if (!Modifiers)
+    return false;
+  return (Modifiers->Modifiers & ModifierOptions::Unaligned) !=
+         ModifierOptions::None;
+}
+
+bool NativeTypeUDT::isVolatileType() const {
+  if (!Modifiers)
+    return false;
+  return (Modifiers->Modifiers & ModifierOptions::Volatile) !=
+         ModifierOptions::None;
+}

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/SymbolCache.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/SymbolCache.cpp?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/SymbolCache.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/SymbolCache.cpp Fri Sep 21 15:36:04 2018
@@ -1,6 +1,7 @@
 #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
 
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
@@ -9,6 +10,7 @@
 #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
 #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
 #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
@@ -50,10 +52,18 @@ SymbolCache::SymbolCache(NativeSession &
 
   if (Dbi)
     Compilands.resize(Dbi->modules().getModuleCount());
+
+  auto &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
+  Tpi.buildHashMap();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
+  return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
 }
 
 std::unique_ptr<IPDBEnumSymbols>
-SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) {
+SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
   auto Tpi = Session.getPDBFile().getPDBTpiStream();
   if (!Tpi) {
     consumeError(Tpi.takeError());
@@ -61,7 +71,7 @@ SymbolCache::createTypeEnumerator(codevi
   }
   auto &Types = Tpi->typeCollection();
   return std::unique_ptr<IPDBEnumSymbols>(
-      new NativeEnumTypes(Session, Types, Kind));
+      new NativeEnumTypes(Session, Types, std::move(Kinds)));
 }
 
 SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
@@ -98,38 +108,24 @@ SymbolCache::createSymbolForModifiedType
   if (Record.ModifiedType.isSimple())
     return createSimpleType(Record.ModifiedType, Record.Modifiers);
 
-  auto Tpi = Session.getPDBFile().getPDBTpiStream();
-  if (!Tpi) {
-    consumeError(Tpi.takeError());
-    return 0;
-  }
-  codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
-
-  codeview::CVType UnmodifiedType = Types.getType(Record.ModifiedType);
-
-  switch (UnmodifiedType.kind()) {
-  case LF_ENUM: {
-    EnumRecord ER;
-    if (auto EC =
-            TypeDeserializer::deserializeAs<EnumRecord>(UnmodifiedType, ER)) {
-      consumeError(std::move(EC));
-      return 0;
-    }
-    return createSymbol<NativeTypeEnum>(Record.ModifiedType, std::move(Record),
-                                        std::move(ER));
-  }
-  case LF_STRUCTURE:
-  case LF_UNION:
-  case LF_CLASS:
-    // FIXME: Handle these
-    break;
+  // Make sure we create and cache a record for the unmodified type.
+  SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
+  NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
+
+  switch (UnmodifiedNRS.getSymTag()) {
+  case PDB_SymType::Enum:
+    return createSymbol<NativeTypeEnum>(
+        static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
+  case PDB_SymType::UDT:
+    return createSymbol<NativeTypeUDT>(
+        static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
   default:
     // No other types can be modified.  (LF_POINTER, for example, records
     // its modifiers a different way.
     assert(false && "Invalid LF_MODIFIER record");
     break;
   }
-  return createSymbolPlaceholder();
+  return 0;
 }
 
 SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
@@ -150,13 +146,37 @@ SymIndexId SymbolCache::findSymbolByType
   }
   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
   codeview::CVType CVT = Types.getType(Index);
-  // TODO(amccarth):  Make this handle all types.
-  SymIndexId Id = 0;
 
+  if (isUdtForwardRef(CVT)) {
+    Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
+
+    if (!EFD)
+      consumeError(EFD.takeError());
+    else if (*EFD != Index) {
+      assert(!isUdtForwardRef(Types.getType(*EFD)));
+      SymIndexId Result = findSymbolByTypeIndex(*EFD);
+      // Record a mapping from ForwardRef -> SymIndex of complete type so that
+      // we'll take the fast path next time.
+      TypeIndexToSymbolId[Index] = Result;
+      return Result;
+    }
+  }
+
+  // At this point if we still have a forward ref udt it means the full decl was
+  // not in the PDB.  We just have to deal with it and use the forward ref.
+  SymIndexId Id = 0;
   switch (CVT.kind()) {
   case codeview::LF_ENUM:
     Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
     break;
+  case codeview::LF_CLASS:
+  case codeview::LF_STRUCTURE:
+  case codeview::LF_INTERFACE:
+    Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
+    break;
+  case codeview::LF_UNION:
+    Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
+    break;
   case codeview::LF_POINTER:
     Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
                                                                std::move(CVT));

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp Fri Sep 21 15:36:04 2018
@@ -11,9 +11,8 @@
 
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
-#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
-#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
 #include "llvm/DebugInfo/PDB/Native/Hash.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
@@ -161,35 +160,6 @@ void TpiStream::buildHashMap() {
 
 bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); }
 
-template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) {
-  RecordT Record;
-  if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) {
-    consumeError(std::move(EC));
-    return ClassOptions::None;
-  }
-  return Record.getOptions();
-}
-
-static bool isUdtForwardRef(CVType CVT) {
-  ClassOptions UdtOptions = ClassOptions::None;
-  switch (CVT.kind()) {
-  case LF_STRUCTURE:
-  case LF_CLASS:
-  case LF_INTERFACE:
-    UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT));
-    break;
-  case LF_ENUM:
-    UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT));
-    break;
-  case LF_UNION:
-    UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT));
-    break;
-  default:
-    return false;
-  }
-  return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None;
-}
-
 Expected<TypeIndex>
 TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const {
   CVType F = Types->getType(ForwardRefTI);

Added: llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-udts.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-udts.test?rev=342779&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-udts.test (added)
+++ llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-udts.test Fri Sep 21 15:36:04 2018
@@ -0,0 +1,539 @@
+; RUN: llvm-pdbutil pretty -native -classes %p/../Inputs/every-class.pdb \
+; RUN:     | FileCheck -check-prefix=PRETTY %s
+
+; RUN: llvm-pdbutil diadump -native -udts %p/../Inputs/every-class.pdb \
+; RUN:     | FileCheck -check-prefix=DUMP %s
+
+
+PRETTY: struct main::__l2::<unnamed-type-Anonymous> [sizeof = 1]
+PRETTY: struct main::__l2::Scoped [sizeof = 1]
+PRETTY: struct __vc_attributes::event_sourceAttribute [sizeof = 12]
+PRETTY: struct __vc_attributes::helper_attributes::v1_alttypeAttribute [sizeof = 4]
+PRETTY: struct __vc_attributes::helper_attributes::usageAttribute [sizeof = 4]
+PRETTY: struct __vc_attributes::threadingAttribute [sizeof = 4]
+PRETTY: struct __vc_attributes::aggregatableAttribute [sizeof = 4]
+PRETTY: struct __vc_attributes::event_receiverAttribute [sizeof = 8]
+PRETTY: struct __vc_attributes::moduleAttribute [sizeof = 96]
+PRETTY: struct Nested [sizeof = 1]
+PRETTY: struct Nested::F [sizeof = 1]
+PRETTY: struct Constructor [sizeof = 1]
+PRETTY: class Class [sizeof = 1]
+PRETTY: union Union [sizeof = 1]
+PRETTY: struct Operator [sizeof = 1]
+PRETTY: struct Cast [sizeof = 1]
+PRETTY: struct Nothing [sizeof = 1]
+PRETTY: struct Assignment [sizeof = 1]
+PRETTY: const struct Nothing
+PRETTY: volatile struct Nothing
+PRETTY: const volatile struct Nothing
+PRETTY: unaligned struct Nothing
+
+; DUMP:      {
+; DUMP-NEXT:   symIndexId: 2
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: main::__l2::<unnamed-type-Anonymous>
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 1
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 4
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: main::__l2::Scoped
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 1
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 5
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: __vc_attributes::event_sourceAttribute
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 12
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 1
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 1
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 6
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: __vc_attributes::helper_attributes::v1_alttypeAttribute
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 4
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 1
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 1
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 7
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: __vc_attributes::helper_attributes::usageAttribute
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 4
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 1
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 1
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 8
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: __vc_attributes::threadingAttribute
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 4
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 1
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 1
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 9
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: __vc_attributes::aggregatableAttribute
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 4
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 1
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 1
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 10
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: __vc_attributes::event_receiverAttribute
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 8
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 1
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 1
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 11
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: __vc_attributes::moduleAttribute
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 96
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 1
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 1
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 12
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Nested
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 1
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 13
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Nested::F
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 1
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 14
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Constructor
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 1
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 15
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Class
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: class
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 16
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Union
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: union
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 17
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Operator
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 1
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 18
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Cast
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 1
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 1
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 19
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Nothing
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 20
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Assignment
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 1
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 1
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 21
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Nothing
+; DUMP-NEXT:   unmodifiedTypeId: 19
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 1
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 22
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Nothing
+; DUMP-NEXT:   unmodifiedTypeId: 19
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 1
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 23
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Nothing
+; DUMP-NEXT:   unmodifiedTypeId: 19
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 1
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 0
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 1
+; DUMP-NEXT: }
+; DUMP-NEXT: {
+; DUMP-NEXT:   symIndexId: 24
+; DUMP-NEXT:   symTag: UDT
+; DUMP-NEXT:   name: Nothing
+; DUMP-NEXT:   unmodifiedTypeId: 19
+; DUMP-NEXT:   virtualTableShapeId: 3
+; DUMP-NEXT:   length: 1
+; DUMP-NEXT:   udtKind: struct
+; DUMP-NEXT:   constructor: 0
+; DUMP-NEXT:   constType: 0
+; DUMP-NEXT:   hasAssignmentOperator: 0
+; DUMP-NEXT:   hasCastOperator: 0
+; DUMP-NEXT:   hasNestedTypes: 0
+; DUMP-NEXT:   overloadedOperator: 0
+; DUMP-NEXT:   isInterfaceUdt: 0
+; DUMP-NEXT:   intrinsic: 0
+; DUMP-NEXT:   nested: 0
+; DUMP-NEXT:   packed: 0
+; DUMP-NEXT:   isRefUdt: 0
+; DUMP-NEXT:   scoped: 0
+; DUMP-NEXT:   unalignedType: 1
+; DUMP-NEXT:   isValueUdt: 0
+; DUMP-NEXT:   volatileType: 0
+; DUMP-NEXT: }

Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp?rev=342779&r1=342778&r2=342779&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp Fri Sep 21 15:36:04 2018
@@ -986,6 +986,8 @@ static void dumpDia(StringRef Path) {
     SymTypes.push_back(PDB_SymType::Enum);
   if (opts::diadump::Pointers)
     SymTypes.push_back(PDB_SymType::PointerType);
+  if (opts::diadump::UDTs)
+    SymTypes.push_back(PDB_SymType::UDT);
 
   PdbSymbolIdField Ids = opts::diadump::NoSymIndexIds ? PdbSymbolIdField::None
                                                       : PdbSymbolIdField::All;
@@ -1011,6 +1013,8 @@ static void dumpDia(StringRef Path) {
       outs() << "\n}\n";
     }
   }
+  auto Child = Session->getSymbolById(3);
+  Child->defaultDump(outs(), 2, PdbSymbolIdField::All, PdbSymbolIdField::None);
 }
 
 static void dumpPretty(StringRef Path) {




More information about the llvm-commits mailing list