OSDN Git Service

[PDB] Make the native reader support enumerators.
authorZachary Turner <zturner@google.com>
Mon, 17 Sep 2018 21:08:11 +0000 (21:08 +0000)
committerZachary Turner <zturner@google.com>
Mon, 17 Sep 2018 21:08:11 +0000 (21:08 +0000)
Previously we would dump the names of enum types, but not their
enumerator values.  This adds support for enumerator values.  In
doing so, we have to introduce a general purpose mechanism for
caching symbol indices of field list members.  Unlike global
types, FieldList members do not have a TypeIndex.  So instead,
we identify them by the pair {TypeIndexOfFieldList, IndexInFieldList}.

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

15 files changed:
include/llvm/DebugInfo/PDB/IPDBEnumChildren.h
include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h [new file with mode: 0644]
include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h
include/llvm/DebugInfo/PDB/Native/SymbolCache.h
include/llvm/DebugInfo/PDB/PDBTypes.h
lib/DebugInfo/PDB/CMakeLists.txt
lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp [new file with mode: 0644]
lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
lib/DebugInfo/PDB/Native/SymbolCache.cpp
lib/DebugInfo/PDB/PDBExtras.cpp
test/DebugInfo/PDB/Inputs/every-enum.cpp [new file with mode: 0644]
test/DebugInfo/PDB/Inputs/every-enum.pdb [new file with mode: 0644]
test/DebugInfo/PDB/Native/pdb-native-enums.test
tools/llvm-pdbutil/llvm-pdbutil.cpp

index e846ffd..380302e 100644 (file)
@@ -29,6 +29,21 @@ public:
   virtual void reset() = 0;
 };
 
+template <typename ChildType>
+class NullEnumerator : public IPDBEnumChildren<ChildType> {
+  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 {}
+};
+
 } // end namespace pdb
 } // end namespace llvm
 
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h b/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h
new file mode 100644 (file)
index 0000000..925f3f1
--- /dev/null
@@ -0,0 +1,50 @@
+//===- NativeSymbolEnumerator.h - info about enumerator values --*- 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_NATIVESYMBOLENUMERATOR_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVESYMBOLENUMERATOR_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+class NativeTypeEnum;
+
+class NativeSymbolEnumerator : public NativeRawSymbol {
+public:
+  NativeSymbolEnumerator(NativeSession &Session, SymIndexId Id,
+                         const NativeTypeEnum &Parent,
+                         codeview::EnumeratorRecord Record);
+
+  ~NativeSymbolEnumerator() override;
+
+  void dump(raw_ostream &OS, int Indent) const override;
+
+  SymIndexId getClassParentId() const override;
+  SymIndexId getLexicalParentId() const override;
+  std::string getName() const override;
+  SymIndexId getTypeId() const override;
+  PDB_DataKind getDataKind() const override;
+  PDB_LocType getLocationType() const override;
+  bool isConstType() const override;
+  bool isVolatileType() const override;
+  bool isUnalignedType() const override;
+  Variant getValue() const override;
+
+protected:
+  const NativeTypeEnum &Parent;
+  codeview::EnumeratorRecord Record;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEENUM_H
index 35a9766..c8eab14 100644 (file)
@@ -18,6 +18,8 @@
 namespace llvm {
 namespace pdb {
 
+class NativeTypeBuiltin;
+
 class NativeTypeEnum : public NativeRawSymbol {
 public:
   NativeTypeEnum(NativeSession &Session, SymIndexId Id, codeview::TypeIndex TI,
@@ -56,6 +58,8 @@ public:
   bool isValueUdt() const override;
   bool isInterfaceUdt() const override;
 
+  const NativeTypeBuiltin &getUnderlyingBuiltinType() const;
+
 protected:
   codeview::TypeIndex Index;
   codeview::EnumRecord Record;
index 704f8b2..3ef01c4 100644 (file)
@@ -31,6 +31,8 @@ class SymbolCache {
 
   std::vector<std::unique_ptr<NativeRawSymbol>> Cache;
   DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
+  DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
+      FieldListMembersToSymbolId;
   std::vector<SymIndexId> Compilands;
 
   SymIndexId createSymbolPlaceholder() {
@@ -77,6 +79,23 @@ public:
 
   SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
 
+  template <typename ConcreteSymbolT, typename... Args>
+  SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,
+                                        uint32_t Index,
+                                        Args &&... ConstructorArgs) {
+    SymIndexId SymId = Cache.size();
+    std::pair<codeview::TypeIndex, uint32_t> Key{FieldListTI, Index};
+    auto Result = FieldListMembersToSymbolId.try_emplace(Key, SymId);
+    if (Result.second) {
+      auto NewSymbol = llvm::make_unique<ConcreteSymbolT>(
+          Session, SymId, std::forward<Args>(ConstructorArgs)...);
+      Cache.push_back(std::move(NewSymbol));
+    } else {
+      SymId = Result.first->second;
+    }
+    return SymId;
+  }
+
   std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index);
   uint32_t getNumCompilands() const;
 
index c2b3240..d1d7be6 100644 (file)
@@ -336,6 +336,36 @@ enum PDB_VariantType {
 struct Variant {
   Variant() = default;
 
+  explicit Variant(bool V) : Type(PDB_VariantType::Bool) { Value.Bool = V; }
+  explicit Variant(int8_t V) : Type(PDB_VariantType::Int8) { Value.Int8 = V; }
+  explicit Variant(int16_t V) : Type(PDB_VariantType::Int16) {
+    Value.Int16 = V;
+  }
+  explicit Variant(int32_t V) : Type(PDB_VariantType::Int32) {
+    Value.Int32 = V;
+  }
+  explicit Variant(int64_t V) : Type(PDB_VariantType::Int64) {
+    Value.Int64 = V;
+  }
+  explicit Variant(float V) : Type(PDB_VariantType::Single) {
+    Value.Single = V;
+  }
+  explicit Variant(double V) : Type(PDB_VariantType::Double) {
+    Value.Double = V;
+  }
+  explicit Variant(uint8_t V) : Type(PDB_VariantType::UInt8) {
+    Value.UInt8 = V;
+  }
+  explicit Variant(uint16_t V) : Type(PDB_VariantType::UInt16) {
+    Value.UInt16 = V;
+  }
+  explicit Variant(uint32_t V) : Type(PDB_VariantType::UInt32) {
+    Value.UInt32 = V;
+  }
+  explicit Variant(uint64_t V) : Type(PDB_VariantType::UInt64) {
+    Value.UInt64 = V;
+  }
+
   Variant(const Variant &Other) {
     *this = Other;
   }
index 5e52515..8bf16c5 100644 (file)
@@ -51,6 +51,7 @@ add_pdb_impl_folder(Native
   Native/NativeEnumTypes.cpp
   Native/NativeExeSymbol.cpp
   Native/NativeRawSymbol.cpp
+  Native/NativeSymbolEnumerator.cpp
   Native/NativeTypeBuiltin.cpp
   Native/NativeTypeEnum.cpp
   Native/NativeTypePointer.cpp
index 95aab9f..0b4b127 100644 (file)
@@ -141,6 +141,15 @@ PrivateGetDIAValue(IDiaSymbol *Symbol,
   return IdResult;
 }
 
+template <typename PrintType, typename ArgType>
+void DumpDIAValueAs(llvm::raw_ostream &OS, int Indent, StringRef Name,
+                    IDiaSymbol *Symbol,
+                    HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
+  ArgType Value;
+  if (S_OK == (Symbol->*Method)(&Value))
+    dumpSymbolField(OS, Name, static_cast<PrintType>(Value), Indent);
+}
+
 template <typename ArgType>
 void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
                   IDiaSymbol *Symbol,
@@ -194,6 +203,10 @@ DIARawSymbol::DIARawSymbol(const DIASession &PDBSession,
   DumpDIAValue(Stream, Indent, StringRef{#Method}, Symbol,                     \
                &IDiaSymbol::get_##Method);
 
+#define RAW_METHOD_DUMP_AS(Stream, Method, Type)                               \
+  DumpDIAValueAs<Type>(Stream, Indent, StringRef{#Method}, Symbol,             \
+                       &IDiaSymbol::get_##Method);
+
 void DIARawSymbol::dump(raw_ostream &OS, int Indent) const {
   RAW_METHOD_DUMP(OS, symIndexId);
   RAW_METHOD_DUMP(OS, symTag);
@@ -267,12 +280,12 @@ void DIARawSymbol::dump(raw_ostream &OS, int Indent) const {
   RAW_METHOD_DUMP(OS, virtualBaseDispIndex);
   RAW_METHOD_DUMP(OS, virtualBaseOffset);
   RAW_METHOD_DUMP(OS, virtualTableShapeId);
-  RAW_METHOD_DUMP(OS, dataKind);
+  RAW_METHOD_DUMP_AS(OS, dataKind, PDB_DataKind);
   RAW_METHOD_DUMP(OS, guid);
   RAW_METHOD_DUMP(OS, offset);
   RAW_METHOD_DUMP(OS, thisAdjust);
   RAW_METHOD_DUMP(OS, virtualBasePointerOffset);
-  RAW_METHOD_DUMP(OS, locationType);
+  RAW_METHOD_DUMP_AS(OS, locationType, PDB_LocType);
   RAW_METHOD_DUMP(OS, machineType);
   RAW_METHOD_DUMP(OS, thunkOrdinal);
   RAW_METHOD_DUMP(OS, length);
diff --git a/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp b/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
new file mode 100644 (file)
index 0000000..18b13b0
--- /dev/null
@@ -0,0 +1,116 @@
+//===- NativeSymbolEnumerator.cpp - info about enumerators ------*- 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/NativeSymbolEnumerator.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeSymbolEnumerator::NativeSymbolEnumerator(
+    NativeSession &Session, SymIndexId Id, const NativeTypeEnum &Parent,
+    codeview::EnumeratorRecord Record)
+    : NativeRawSymbol(Session, PDB_SymType::Data, Id), Parent(Parent),
+      Record(std::move(Record)) {}
+
+NativeSymbolEnumerator::~NativeSymbolEnumerator() {}
+
+void NativeSymbolEnumerator::dump(raw_ostream &OS, int Indent) const {
+  NativeRawSymbol::dump(OS, Indent);
+  dumpSymbolField(OS, "classParentId", getClassParentId(), Indent);
+  dumpSymbolField(OS, "lexicalParentId", getLexicalParentId(), Indent);
+  dumpSymbolField(OS, "name", getName(), Indent);
+  dumpSymbolField(OS, "typeId", getTypeId(), Indent);
+  dumpSymbolField(OS, "dataKind", getDataKind(), Indent);
+  dumpSymbolField(OS, "locationType", getLocationType(), Indent);
+  dumpSymbolField(OS, "constType", isConstType(), Indent);
+  dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+  dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+  dumpSymbolField(OS, "value", getValue(), Indent);
+}
+
+SymIndexId NativeSymbolEnumerator::getClassParentId() const {
+  return Parent.getSymIndexId();
+}
+
+SymIndexId NativeSymbolEnumerator::getLexicalParentId() const { return 0; }
+
+std::string NativeSymbolEnumerator::getName() const { return Record.Name; }
+
+SymIndexId NativeSymbolEnumerator::getTypeId() const {
+  return Parent.getTypeId();
+}
+
+PDB_DataKind NativeSymbolEnumerator::getDataKind() const {
+  return PDB_DataKind::Constant;
+}
+
+PDB_LocType NativeSymbolEnumerator::getLocationType() const {
+  return PDB_LocType::Constant;
+}
+
+bool NativeSymbolEnumerator::isConstType() const { return false; }
+
+bool NativeSymbolEnumerator::isVolatileType() const { return false; }
+
+bool NativeSymbolEnumerator::isUnalignedType() const { return false; }
+
+Variant NativeSymbolEnumerator::getValue() const {
+  const NativeTypeBuiltin &BT = Parent.getUnderlyingBuiltinType();
+
+  switch (BT.getBuiltinType()) {
+  case PDB_BuiltinType::Int:
+  case PDB_BuiltinType::Long:
+  case PDB_BuiltinType::Char: {
+    assert(Record.Value.isSignedIntN(BT.getLength() * 8));
+    int64_t N = Record.Value.getSExtValue();
+    switch (BT.getLength()) {
+    case 1:
+      return Variant{static_cast<int8_t>(N)};
+    case 2:
+      return Variant{static_cast<int16_t>(N)};
+    case 4:
+      return Variant{static_cast<int32_t>(N)};
+    case 8:
+      return Variant{static_cast<int64_t>(N)};
+    }
+    break;
+  }
+  case PDB_BuiltinType::UInt:
+  case PDB_BuiltinType::ULong: {
+    assert(Record.Value.isIntN(BT.getLength() * 8));
+    uint64_t U = Record.Value.getZExtValue();
+    switch (BT.getLength()) {
+    case 1:
+      return Variant{static_cast<uint8_t>(U)};
+    case 2:
+      return Variant{static_cast<uint16_t>(U)};
+    case 4:
+      return Variant{static_cast<uint32_t>(U)};
+    case 8:
+      return Variant{static_cast<uint64_t>(U)};
+    }
+    break;
+  }
+  case PDB_BuiltinType::Bool: {
+    assert(Record.Value.isIntN(BT.getLength() * 8));
+    uint64_t U = Record.Value.getZExtValue();
+    return Variant{static_cast<bool>(U)};
+  }
+  default:
+    assert(false && "Invalid enumeration type");
+    break;
+  }
+
+  return Variant{Record.Value.getSExtValue()};
+}
index cfc767f..e833b6d 100644 (file)
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
 
 #include "llvm/Support/FormatVariadic.h"
@@ -23,6 +27,95 @@ using namespace llvm;
 using namespace llvm::codeview;
 using namespace llvm::pdb;
 
+namespace {
+// Yea, this is a pretty terrible class name.  But if we have an enum:
+//
+// enum Foo {
+//  A,
+//  B
+// };
+//
+// then A and B are the "enumerators" of the "enum" Foo.  And we need
+// to enumerate them.
+class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
+public:
+  NativeEnumEnumEnumerators(NativeSession &Session,
+                            const NativeTypeEnum &ClassParent,
+                            const codeview::EnumRecord &CVEnum);
+
+  uint32_t getChildCount() const override;
+  std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+  std::unique_ptr<PDBSymbol> getNext() override;
+  void reset() override;
+
+private:
+  Error visitKnownMember(CVMemberRecord &CVM,
+                         EnumeratorRecord &Record) override;
+  Error visitKnownMember(CVMemberRecord &CVM,
+                         ListContinuationRecord &Record) override;
+
+  NativeSession &Session;
+  const NativeTypeEnum &ClassParent;
+  const codeview::EnumRecord &CVEnum;
+  std::vector<EnumeratorRecord> Enumerators;
+  Optional<TypeIndex> ContinuationIndex;
+  uint32_t Index = 0;
+};
+} // namespace
+
+NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
+    NativeSession &Session, const NativeTypeEnum &ClassParent,
+    const codeview::EnumRecord &CVEnum)
+    : Session(Session), ClassParent(ClassParent), CVEnum(CVEnum) {
+  TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
+  LazyRandomTypeCollection &Types = Tpi.typeCollection();
+
+  ContinuationIndex = CVEnum.FieldList;
+  while (ContinuationIndex) {
+    CVType FieldList = Types.getType(*ContinuationIndex);
+    assert(FieldList.kind() == LF_FIELDLIST);
+    ContinuationIndex.reset();
+    cantFail(visitMemberRecordStream(FieldList.data(), *this));
+  }
+}
+
+Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
+                                                  EnumeratorRecord &Record) {
+  Enumerators.push_back(Record);
+  return Error::success();
+}
+
+Error NativeEnumEnumEnumerators::visitKnownMember(
+    CVMemberRecord &CVM, ListContinuationRecord &Record) {
+  ContinuationIndex = Record.ContinuationIndex;
+  return Error::success();
+}
+
+uint32_t NativeEnumEnumEnumerators::getChildCount() const {
+  return Enumerators.size();
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
+  if (Index >= getChildCount())
+    return nullptr;
+
+  SymIndexId Id =
+      Session.getSymbolCache()
+          .getOrCreateFieldListMember<NativeSymbolEnumerator>(
+              CVEnum.FieldList, Index, ClassParent, Enumerators[Index]);
+  return Session.getSymbolCache().getSymbolById(Id);
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
+  if (Index >= getChildCount())
+    return nullptr;
+
+  return getChildAtIndex(Index++);
+}
+
+void NativeEnumEnumEnumerators::reset() { Index = 0; }
+
 NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
                                TypeIndex Index, EnumRecord Record)
     : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
@@ -67,14 +160,20 @@ void NativeTypeEnum::dump(raw_ostream &OS, int Indent) const {
 
 std::unique_ptr<IPDBEnumSymbols>
 NativeTypeEnum::findChildren(PDB_SymType Type) const {
-  switch (Type) {
-  case PDB_SymType::Data: {
-    // TODO(amccarth) :  Provide an actual implementation.
-    return nullptr;
-  }
-  default:
-    return nullptr;
+  if (Type != PDB_SymType::Data)
+    return llvm::make_unique<NullEnumerator<PDBSymbol>>();
+
+  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);
 }
 
 PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
@@ -86,8 +185,9 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
 
   // This indicates a corrupt record.
   if (!Underlying.isSimple() ||
-      Underlying.getSimpleMode() != SimpleTypeMode::Direct)
+      Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
     return PDB_BuiltinType::None;
+  }
 
   switch (Underlying.getSimpleKind()) {
   case SimpleTypeKind::Boolean128:
@@ -98,6 +198,7 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
     return PDB_BuiltinType::Bool;
   case SimpleTypeKind::NarrowCharacter:
   case SimpleTypeKind::UnsignedCharacter:
+  case SimpleTypeKind::SignedCharacter:
     return PDB_BuiltinType::Char;
   case SimpleTypeKind::WideCharacter:
     return PDB_BuiltinType::WCharT;
@@ -149,6 +250,7 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
 SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
   if (!Modifiers)
     return 0;
+
   return Session.getSymbolCache().findSymbolByTypeIndex(
       Modifiers->ModifiedType);
 }
@@ -235,3 +337,8 @@ bool NativeTypeEnum::isUnalignedType() const {
   return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
           ModifierOptions::None);
 }
+
+const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
+  return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
+      getTypeId());
+}
index d8b4d59..a4b1ecf 100644 (file)
@@ -26,14 +26,17 @@ static const struct BuiltinTypeEntry {
   PDB_BuiltinType Type;
   uint32_t Size;
 } BuiltinTypes[] = {
+    {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
+    {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
     {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
     {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
+    {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
     {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
+    {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
     {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
     {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
     {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
     {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
-    {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
     {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
     // This table can be grown as necessary, but these are the only types we've
     // needed so far.
@@ -169,6 +172,8 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
 
 std::unique_ptr<PDBSymbol>
 SymbolCache::getSymbolById(SymIndexId SymbolId) const {
+  assert(SymbolId < Cache.size());
+
   // Id 0 is reserved.
   if (SymbolId == 0)
     return nullptr;
index a4e3164..0c5fa42 100644 (file)
@@ -293,7 +293,7 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const Variant &Value) {
       OS << Value.Value.Single;
       break;
     case PDB_VariantType::UInt16:
-      OS << Value.Value.Double;
+      OS << Value.Value.UInt16;
       break;
     case PDB_VariantType::UInt32:
       OS << Value.Value.UInt32;
diff --git a/test/DebugInfo/PDB/Inputs/every-enum.cpp b/test/DebugInfo/PDB/Inputs/every-enum.cpp
new file mode 100644 (file)
index 0000000..5eb0145
--- /dev/null
@@ -0,0 +1,110 @@
+// Build with "cl.exe /Zi /GR- /GX- every-enum.cpp /link /debug /nodefaultlib /incremental:no /entry:main"
+
+#include <stdint.h>
+
+// clang-format off
+void *__purecall = 0;
+
+void __cdecl operator delete(void *,unsigned int) {}
+void __cdecl operator delete(void *,unsigned __int64) {}
+
+
+enum I8 : int8_t {
+  I8A = INT8_MIN,
+  I8B = 0,
+  I8C = INT8_MAX
+};
+
+enum I16 : int16_t {
+  I16A = INT16_MIN,
+  I16B = 0,
+  I16C = INT16_MAX,
+};
+
+enum I32 : int32_t {
+  I32A = INT32_MIN,
+  I32B = 0,
+  I32C = INT32_MAX,
+};
+
+enum I64 : int64_t {
+  I64A = INT64_MIN,
+  I64B = 0,
+  I64C = INT64_MAX,
+};
+
+enum U8 : uint8_t {
+  U8A = 0,
+  U8B = UINT8_MAX
+};
+
+enum U16 : uint16_t {
+  U16A = 0,
+  U16B = UINT16_MAX,
+};
+
+enum U32 : uint32_t {
+  U32A = 0,
+  U32B = UINT32_MAX,
+};
+
+enum U64 : uint64_t {
+  U64A = 0,
+  U64B = UINT64_MAX,
+};
+
+enum Char16 : char16_t {
+  C16A = u'a',
+  C16B = u'b',
+};
+
+enum Char32 : char32_t {
+  C32A = U'a',
+  C32B = U'b',
+};
+
+enum WChar : wchar_t {
+  WCA = L'a',
+  WCB = L'b',
+};
+
+enum Bool : bool {
+  BA = true,
+  BB = false
+};
+
+enum class EC {
+  A = 1,
+  B = 2
+};
+
+struct Struct {
+  enum Nested {
+    A = 1,
+    B = 2
+  };
+};
+
+template<typename T> void f(T t) {}
+
+int main(int argc, char **argv) {
+  f(I8A);
+  f(I16A);
+  f(I32A);
+  f(I64A);
+  f(U8A);
+  f(U16A);
+  f(U32A);
+  f(U64A);
+
+  f(C16A);
+  f(C32A);
+  f(WCA);
+  f(BA);
+
+
+  f(EC::A);
+  f(Struct::A);
+
+  f<const volatile EC>(EC::A);
+}
diff --git a/test/DebugInfo/PDB/Inputs/every-enum.pdb b/test/DebugInfo/PDB/Inputs/every-enum.pdb
new file mode 100644 (file)
index 0000000..23f5b4f
Binary files /dev/null and b/test/DebugInfo/PDB/Inputs/every-enum.pdb differ
index 6777f0b..480fd03 100644 (file)
-; Test that the native PDB reader can enumerate the enum types.
-; RUN: llvm-pdbutil pretty -native -enums %p/../Inputs/every-type.pdb \
+; Test that the native PDB reader can enumerate the enum types.  The output
+; being checked against is golden output generated by llvm-pdbutil without
+; the -native flag.  Then we check that we generate the same output.
+; Unfortunately since we generate a slightly different (albeit correct)
+; class / parent hierarchy, if you re-generate this file you will need to
+; actually use the output from llvm-pdbutil *with* the -native flag, but
+; before "blessing" it, manually diff against the golden output from
+; llvm-pdbutil without the -native flag and verifying that there are no
+; substantive differences aside from the various symbol ids.
+
+; RUN: llvm-pdbutil pretty -native -enums %p/../Inputs/every-enum.pdb \
 ; RUN:   | FileCheck -check-prefix=ENUMS %s
-; RUN: llvm-pdbutil diadump -native -enums %p/../Inputs/every-type.pdb \
+; RUN: llvm-pdbutil diadump -native -enums %p/../Inputs/every-enum.pdb \
 ; RUN:   | FileCheck -check-prefix=DUMP %s
 
-ENUMS:  enum FooClass::NestedEnum {
-ENUMS-NEXT:  }
-ENUMS:  const volatile enum FooClass::NestedEnum
 
-DUMP:      {
-DUMP-NEXT:   symIndexId: 2
-DUMP-NEXT:   symTag: 12
-DUMP-NEXT:   baseType: 6
-DUMP-NEXT:   lexicalParentId: 0
-DUMP-NEXT:   name: FooClass::NestedEnum
-DUMP-NEXT:   typeId: 3
-DUMP-NEXT:   length: 4
-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: 4
-DUMP-NEXT:   symTag: 12
-DUMP-NEXT:   baseType: 6
-DUMP-NEXT:   lexicalParentId: 0
-DUMP-NEXT:   name: __vc_attributes::event_sourceAttribute::type_e
-DUMP-NEXT:   typeId: 3
-DUMP-NEXT:   length: 4
-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: 5
-DUMP-NEXT:   symTag: 12
-DUMP-NEXT:   baseType: 6
-DUMP-NEXT:   lexicalParentId: 0
-DUMP-NEXT:   name: __vc_attributes::event_sourceAttribute::optimize_e
-DUMP-NEXT:   typeId: 3
-DUMP-NEXT:   length: 4
-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: 6
-DUMP-NEXT:   symTag: 12
-DUMP-NEXT:   baseType: 6
-DUMP-NEXT:   lexicalParentId: 0
-DUMP-NEXT:   name: __vc_attributes::helper_attributes::v1_alttypeAttribute::type_e
-DUMP-NEXT:   typeId: 3
-DUMP-NEXT:   length: 4
-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: 7
-DUMP-NEXT:   symTag: 12
-DUMP-NEXT:   baseType: 6
-DUMP-NEXT:   lexicalParentId: 0
-DUMP-NEXT:   name: __vc_attributes::helper_attributes::usageAttribute::usage_e
-DUMP-NEXT:   typeId: 3
-DUMP-NEXT:   length: 4
-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: 8
-DUMP-NEXT:   symTag: 12
-DUMP-NEXT:   baseType: 6
-DUMP-NEXT:   lexicalParentId: 0
-DUMP-NEXT:   name: __vc_attributes::threadingAttribute::threading_e
-DUMP-NEXT:   typeId: 3
-DUMP-NEXT:   length: 4
-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: 9
-DUMP-NEXT:   symTag: 12
-DUMP-NEXT:   baseType: 6
-DUMP-NEXT:   lexicalParentId: 0
-DUMP-NEXT:   name: __vc_attributes::aggregatableAttribute::type_e
-DUMP-NEXT:   typeId: 3
-DUMP-NEXT:   length: 4
-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: 10
-DUMP-NEXT:   symTag: 12
-DUMP-NEXT:   baseType: 6
-DUMP-NEXT:   lexicalParentId: 0
-DUMP-NEXT:   name: __vc_attributes::event_receiverAttribute::type_e
-DUMP-NEXT:   typeId: 3
-DUMP-NEXT:   length: 4
-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: 11
-DUMP-NEXT:   symTag: 12
-DUMP-NEXT:   baseType: 6
-DUMP-NEXT:   lexicalParentId: 0
-DUMP-NEXT:   name: __vc_attributes::moduleAttribute::type_e
-DUMP-NEXT:   typeId: 3
-DUMP-NEXT:   length: 4
-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: 12
-DUMP-NEXT:   symTag: 12
-DUMP-NEXT:   baseType: 6
-DUMP-NEXT:   lexicalParentId: 0
-DUMP-NEXT:   name: FooClass::NestedEnum
-DUMP-NEXT:   typeId: 3
-DUMP-NEXT:   length: 4
-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: 1
-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: }
+ENUMS: enum I8 : char {
+ENUMS:   I8A = -128
+ENUMS:   I8B = 0
+ENUMS:   I8C = 127
+ENUMS: }
+ENUMS: enum I16 : short {
+ENUMS:   I16A = -32768
+ENUMS:   I16B = 0
+ENUMS:   I16C = 32767
+ENUMS: }
+ENUMS: enum I32 {
+ENUMS:   I32A = -2147483648
+ENUMS:   I32B = 0
+ENUMS:   I32C = 2147483647
+ENUMS: }
+ENUMS: enum I64 : __int64 {
+ENUMS:   I64A = -9223372036854775808
+ENUMS:   I64B = 0
+ENUMS:   I64C = 9223372036854775807
+ENUMS: }
+ENUMS: enum U8 : unsigned char {
+ENUMS:   U8A = 0
+ENUMS:   U8B = 255
+ENUMS: }
+ENUMS: enum U16 : unsigned short {
+ENUMS:   U16A = 0
+ENUMS:   U16B = 65535
+ENUMS: }
+ENUMS: enum U32 : unsigned int {
+ENUMS:   U32A = 0
+ENUMS:   U32B = 4294967295
+ENUMS: }
+ENUMS: enum U64 : unsigned __int64 {
+ENUMS:   U64A = 0
+; FIXME: This should be UINT64_MAX.  Is the compiler encoding it wrong or
+; are we decoding it wrong?
+ENUMS:   U64B = 255
+ENUMS: }
+ENUMS: enum Char16 : unsigned short {
+ENUMS:   C16A = 97
+ENUMS:   C16B = 98
+ENUMS: }
+ENUMS: enum Char32 : unsigned int {
+ENUMS:   C32A = 97
+ENUMS:   C32B = 98
+ENUMS: }
+ENUMS: enum WChar : unsigned short {
+ENUMS:   WCA = 97
+ENUMS:   WCB = 98
+ENUMS: }
+ENUMS: enum Bool : bool {
+ENUMS:   BA = true
+ENUMS:   BB = false
+ENUMS: }
+ENUMS: enum EC {
+ENUMS:   A = 1
+ENUMS:   B = 2
+ENUMS: }
+ENUMS: enum Struct::Nested {
+ENUMS:   A = 1
+ENUMS:   B = 2
+ENUMS: }
+ENUMS: const volatile enum EC
+
+
+DUMP: {
+DUMP:   symIndexId: 2
+DUMP:   symTag: 12
+DUMP:   baseType: 2
+DUMP:   lexicalParentId: 0
+DUMP:   name: I8
+DUMP:   typeId: 3
+DUMP:   length: 1
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 4
+DUMP:     symTag: 7
+DUMP:     classParentId: 2
+DUMP:     lexicalParentId: 0
+DUMP:     name: I8A
+DUMP:     typeId: 3
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: -128
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 5
+DUMP:     symTag: 7
+DUMP:     classParentId: 2
+DUMP:     lexicalParentId: 0
+DUMP:     name: I8B
+DUMP:     typeId: 3
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 0
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 6
+DUMP:     symTag: 7
+DUMP:     classParentId: 2
+DUMP:     lexicalParentId: 0
+DUMP:     name: I8C
+DUMP:     typeId: 3
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 127
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 7
+DUMP:   symTag: 12
+DUMP:   baseType: 6
+DUMP:   lexicalParentId: 0
+DUMP:   name: I16
+DUMP:   typeId: 8
+DUMP:   length: 2
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 9
+DUMP:     symTag: 7
+DUMP:     classParentId: 7
+DUMP:     lexicalParentId: 0
+DUMP:     name: I16A
+DUMP:     typeId: 8
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: -32768
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 10
+DUMP:     symTag: 7
+DUMP:     classParentId: 7
+DUMP:     lexicalParentId: 0
+DUMP:     name: I16B
+DUMP:     typeId: 8
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 0
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 11
+DUMP:     symTag: 7
+DUMP:     classParentId: 7
+DUMP:     lexicalParentId: 0
+DUMP:     name: I16C
+DUMP:     typeId: 8
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 32767
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 12
+DUMP:   symTag: 12
+DUMP:   baseType: 6
+DUMP:   lexicalParentId: 0
+DUMP:   name: I32
+DUMP:   typeId: 13
+DUMP:   length: 4
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 14
+DUMP:     symTag: 7
+DUMP:     classParentId: 12
+DUMP:     lexicalParentId: 0
+DUMP:     name: I32A
+DUMP:     typeId: 13
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: -2147483648
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 15
+DUMP:     symTag: 7
+DUMP:     classParentId: 12
+DUMP:     lexicalParentId: 0
+DUMP:     name: I32B
+DUMP:     typeId: 13
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 0
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 16
+DUMP:     symTag: 7
+DUMP:     classParentId: 12
+DUMP:     lexicalParentId: 0
+DUMP:     name: I32C
+DUMP:     typeId: 13
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 2147483647
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 17
+DUMP:   symTag: 12
+DUMP:   baseType: 6
+DUMP:   lexicalParentId: 0
+DUMP:   name: I64
+DUMP:   typeId: 18
+DUMP:   length: 8
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 19
+DUMP:     symTag: 7
+DUMP:     classParentId: 17
+DUMP:     lexicalParentId: 0
+DUMP:     name: I64A
+DUMP:     typeId: 18
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: -9223372036854775808
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 20
+DUMP:     symTag: 7
+DUMP:     classParentId: 17
+DUMP:     lexicalParentId: 0
+DUMP:     name: I64B
+DUMP:     typeId: 18
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 0
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 21
+DUMP:     symTag: 7
+DUMP:     classParentId: 17
+DUMP:     lexicalParentId: 0
+DUMP:     name: I64C
+DUMP:     typeId: 18
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 9223372036854775807
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 22
+DUMP:   symTag: 12
+DUMP:   baseType: 2
+DUMP:   lexicalParentId: 0
+DUMP:   name: U8
+DUMP:   typeId: 23
+DUMP:   length: 1
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 24
+DUMP:     symTag: 7
+DUMP:     classParentId: 22
+DUMP:     lexicalParentId: 0
+DUMP:     name: U8A
+DUMP:     typeId: 23
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 0
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 25
+DUMP:     symTag: 7
+DUMP:     classParentId: 22
+DUMP:     lexicalParentId: 0
+DUMP:     name: U8B
+DUMP:     typeId: 23
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 255
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 26
+DUMP:   symTag: 12
+DUMP:   baseType: 7
+DUMP:   lexicalParentId: 0
+DUMP:   name: U16
+DUMP:   typeId: 27
+DUMP:   length: 2
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 28
+DUMP:     symTag: 7
+DUMP:     classParentId: 26
+DUMP:     lexicalParentId: 0
+DUMP:     name: U16A
+DUMP:     typeId: 27
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 0
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 29
+DUMP:     symTag: 7
+DUMP:     classParentId: 26
+DUMP:     lexicalParentId: 0
+DUMP:     name: U16B
+DUMP:     typeId: 27
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 65535
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 30
+DUMP:   symTag: 12
+DUMP:   baseType: 7
+DUMP:   lexicalParentId: 0
+DUMP:   name: U32
+DUMP:   typeId: 31
+DUMP:   length: 4
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 32
+DUMP:     symTag: 7
+DUMP:     classParentId: 30
+DUMP:     lexicalParentId: 0
+DUMP:     name: U32A
+DUMP:     typeId: 31
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 0
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 33
+DUMP:     symTag: 7
+DUMP:     classParentId: 30
+DUMP:     lexicalParentId: 0
+DUMP:     name: U32B
+DUMP:     typeId: 31
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 4294967295
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 34
+DUMP:   symTag: 12
+DUMP:   baseType: 7
+DUMP:   lexicalParentId: 0
+DUMP:   name: U64
+DUMP:   typeId: 35
+DUMP:   length: 8
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 36
+DUMP:     symTag: 7
+DUMP:     classParentId: 34
+DUMP:     lexicalParentId: 0
+DUMP:     name: U64A
+DUMP:     typeId: 35
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 0
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 37
+DUMP:     symTag: 7
+DUMP:     classParentId: 34
+DUMP:     lexicalParentId: 0
+DUMP:     name: U64B
+DUMP:     typeId: 35
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 255
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 38
+DUMP:   symTag: 12
+DUMP:   baseType: 7
+DUMP:   lexicalParentId: 0
+DUMP:   name: Char16
+DUMP:   typeId: 27
+DUMP:   length: 2
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 39
+DUMP:     symTag: 7
+DUMP:     classParentId: 38
+DUMP:     lexicalParentId: 0
+DUMP:     name: C16A
+DUMP:     typeId: 27
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 97
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 40
+DUMP:     symTag: 7
+DUMP:     classParentId: 38
+DUMP:     lexicalParentId: 0
+DUMP:     name: C16B
+DUMP:     typeId: 27
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 98
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 41
+DUMP:   symTag: 12
+DUMP:   baseType: 7
+DUMP:   lexicalParentId: 0
+DUMP:   name: Char32
+DUMP:   typeId: 42
+DUMP:   length: 4
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 43
+DUMP:     symTag: 7
+DUMP:     classParentId: 41
+DUMP:     lexicalParentId: 0
+DUMP:     name: C32A
+DUMP:     typeId: 42
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 97
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 44
+DUMP:     symTag: 7
+DUMP:     classParentId: 41
+DUMP:     lexicalParentId: 0
+DUMP:     name: C32B
+DUMP:     typeId: 42
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 98
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 45
+DUMP:   symTag: 12
+DUMP:   baseType: 7
+DUMP:   lexicalParentId: 0
+DUMP:   name: WChar
+DUMP:   typeId: 27
+DUMP:   length: 2
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 46
+DUMP:     symTag: 7
+DUMP:     classParentId: 45
+DUMP:     lexicalParentId: 0
+DUMP:     name: WCA
+DUMP:     typeId: 27
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 97
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 47
+DUMP:     symTag: 7
+DUMP:     classParentId: 45
+DUMP:     lexicalParentId: 0
+DUMP:     name: WCB
+DUMP:     typeId: 27
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 98
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 48
+DUMP:   symTag: 12
+DUMP:   baseType: 10
+DUMP:   lexicalParentId: 0
+DUMP:   name: Bool
+DUMP:   typeId: 49
+DUMP:   length: 1
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 50
+DUMP:     symTag: 7
+DUMP:     classParentId: 48
+DUMP:     lexicalParentId: 0
+DUMP:     name: BA
+DUMP:     typeId: 49
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: true
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 51
+DUMP:     symTag: 7
+DUMP:     classParentId: 48
+DUMP:     lexicalParentId: 0
+DUMP:     name: BB
+DUMP:     typeId: 49
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: false
+DUMP:   }
+DUMP: {
+DUMP:   symIndexId: 113
+DUMP:   symTag: 12
+DUMP:   baseType: 6
+DUMP:   lexicalParentId: 0
+DUMP:   name: EC
+DUMP:   typeId: 13
+DUMP:   length: 4
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 114
+DUMP:     symTag: 7
+DUMP:     classParentId: 113
+DUMP:     lexicalParentId: 0
+DUMP:     name: A
+DUMP:     typeId: 13
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 1
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 115
+DUMP:     symTag: 7
+DUMP:     classParentId: 113
+DUMP:     lexicalParentId: 0
+DUMP:     name: B
+DUMP:     typeId: 13
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 2
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 116
+DUMP:   symTag: 12
+DUMP:   baseType: 6
+DUMP:   lexicalParentId: 0
+DUMP:   name: Struct::Nested
+DUMP:   typeId: 13
+DUMP:   length: 4
+DUMP:   constructor: 0
+DUMP:   constType: 0
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 1
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 0
+DUMP:   {
+DUMP:     symIndexId: 114
+DUMP:     symTag: 7
+DUMP:     classParentId: 113
+DUMP:     lexicalParentId: 0
+DUMP:     name: A
+DUMP:     typeId: 13
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 1
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 115
+DUMP:     symTag: 7
+DUMP:     classParentId: 113
+DUMP:     lexicalParentId: 0
+DUMP:     name: B
+DUMP:     typeId: 13
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 2
+DUMP:   }
+DUMP: }
+DUMP: {
+DUMP:   symIndexId: 117
+DUMP:   symTag: 12
+DUMP:   baseType: 6
+DUMP:   lexicalParentId: 0
+DUMP:   name: EC
+DUMP:   typeId: 13
+DUMP:   unmodifiedTypeId: 113
+DUMP:   length: 4
+DUMP:   constructor: 0
+DUMP:   constType: 1
+DUMP:   hasAssignmentOperator: 0
+DUMP:   hasCastOperator: 0
+DUMP:   hasNestedTypes: 0
+DUMP:   overloadedOperator: 0
+DUMP:   isInterfaceUdt: 0
+DUMP:   intrinsic: 0
+DUMP:   nested: 0
+DUMP:   packed: 0
+DUMP:   isRefUdt: 0
+DUMP:   scoped: 0
+DUMP:   unalignedType: 0
+DUMP:   isValueUdt: 0
+DUMP:   volatileType: 1  {
+DUMP:     symIndexId: 114
+DUMP:     symTag: 7
+DUMP:     classParentId: 113
+DUMP:     lexicalParentId: 0
+DUMP:     name: A
+DUMP:     typeId: 13
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 1
+DUMP:   }
+DUMP:   {
+DUMP:     symIndexId: 115
+DUMP:     symTag: 7
+DUMP:     classParentId: 113
+DUMP:     lexicalParentId: 0
+DUMP:     name: B
+DUMP:     typeId: 13
+DUMP:     dataKind: const
+DUMP:     locationType: constant
+DUMP:     constType: 0
+DUMP:     unalignedType: 0
+DUMP:     volatileType: 0
+DUMP:     value: 2
+DUMP:   }
+DUMP: }
index f2adacd..aba5ca9 100644 (file)
@@ -970,6 +970,14 @@ static void dumpDia(StringRef Path) {
     while (auto Child = Children->getNext()) {
       outs() << "{";
       Child->defaultDump(outs(), 2);
+      if (auto Enum = dyn_cast<PDBSymbolTypeEnum>(Child.get())) {
+        auto Enumerators = Enum->findAllChildren<PDBSymbolData>();
+        while (auto Enumerator = Enumerators->getNext()) {
+          outs() << "  {";
+          Enumerator->defaultDump(outs(), 4);
+          outs() << "\n  }\n";
+        }
+      }
       outs() << "\n}\n";
     }
   }