[llvm-pdbdump] Add an option to dump full class definitions.

This adds the --class-definitions flag.  If specified, when dumping
types, instead of "class Foo" you will see the full class definition,
with member functions, constructors, access specifiers.

NOTE: Using this option can be very slow, as generating a full class
definition requires accessing many different parts of the PDB.

llvm-svn: 230203
diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
index 5ed1624..0ce3df5 100644
--- a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
@@ -127,8 +127,9 @@
                   HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
   ArgType Value;
   if (S_OK == (Symbol->*Method)(&Value)) {
+    OS << "\n";
     OS.indent(Indent);
-    OS << Name << ": " << Value << "\n";
+    OS << Name << ": " << Value;
   }
 }
 
@@ -142,8 +143,9 @@
   ArrayRef<char> ByteArray(Bytes, ::SysStringByteLen(Value));
   std::string Result;
   if (llvm::convertUTF16ToUTF8String(ByteArray, Result)) {
+    OS << "\n";
     OS.indent(Indent);
-    OS << Name << ": " << Result << "\n";
+    OS << Name << ": " << Result;
   }
   ::SysFreeString(Value);
 }
@@ -155,8 +157,9 @@
   Value.vt = VT_EMPTY;
   if (S_OK != (Symbol->*Method)(&Value))
     return;
-  Variant V = VariantFromVARIANT(Value);
+  OS << "\n";
   OS.indent(Indent);
+  Variant V = VariantFromVARIANT(Value);
   OS << V;
 }
 }
@@ -201,7 +204,6 @@
   RAW_METHOD_DUMP(OS, get_frontEndMinor)
   RAW_METHOD_DUMP(OS, get_frontEndBuild)
   RAW_METHOD_DUMP(OS, get_frontEndQFE)
-  RAW_METHOD_DUMP(OS, get_count)
   RAW_METHOD_DUMP(OS, get_lexicalParentId)
   RAW_METHOD_DUMP(OS, get_libraryName)
   RAW_METHOD_DUMP(OS, get_liveRangeStartAddressOffset)
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp
index 09b96bc..6bf7e0f 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp
@@ -9,6 +9,7 @@
 
 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
 
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
 #include "llvm/DebugInfo/PDB/PDBSymDumper.h"
 
 #include <utility>
@@ -19,6 +20,10 @@
                              std::unique_ptr<IPDBRawSymbol> DataSymbol)
     : PDBSymbol(PDBSession, std::move(DataSymbol)) {}
 
+std::unique_ptr<PDBSymbol> PDBSymbolData::getType() const {
+  return Session.getSymbolById(getTypeId());
+}
+
 void PDBSymbolData::dump(raw_ostream &OS, int Indent,
                          PDBSymDumper &Dumper) const {
   Dumper.dump(*this, OS, Indent);
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
index 4702d6d..e2d859f 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
@@ -9,13 +9,78 @@
 
 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
 
+#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
 #include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
 #include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
 
+#include <unordered_set>
 #include <utility>
+#include <vector>
 
 using namespace llvm;
+
+namespace {
+class FunctionArgEnumerator : public IPDBEnumChildren<PDBSymbolData> {
+public:
+  typedef ConcreteSymbolEnumerator<PDBSymbolData> ArgEnumeratorType;
+
+  FunctionArgEnumerator(const IPDBSession &PDBSession,
+                        const PDBSymbolFunc &PDBFunc)
+      : Session(PDBSession), Func(PDBFunc) {
+    // Arguments can appear multiple times if they have live range
+    // information, so we only take the first occurrence.
+    std::unordered_set<std::string> SeenNames;
+    auto DataChildren = Func.findAllChildren<PDBSymbolData>();
+    while (auto Child = DataChildren->getNext()) {
+      if (Child->getDataKind() == PDB_DataKind::Param) {
+        std::string Name = Child->getName();
+        if (SeenNames.find(Name) != SeenNames.end())
+          continue;
+        Args.push_back(std::move(Child));
+        SeenNames.insert(Name);
+      }
+    }
+    reset();
+  }
+
+  uint32_t getChildCount() const { return Args.size(); }
+
+  std::unique_ptr<PDBSymbolData> getChildAtIndex(uint32_t Index) const {
+    if (Index >= Args.size())
+      return nullptr;
+
+    return Session.getConcreteSymbolById<PDBSymbolData>(
+        Args[Index]->getSymIndexId());
+  }
+
+  std::unique_ptr<PDBSymbolData> getNext() {
+    if (CurIter == Args.end())
+      return nullptr;
+    const auto &Result = **CurIter;
+    ++CurIter;
+    return Session.getConcreteSymbolById<PDBSymbolData>(Result.getSymIndexId());
+  }
+
+  void reset() { CurIter = Args.empty() ? Args.end() : Args.begin(); }
+
+  FunctionArgEnumerator *clone() const {
+    return new FunctionArgEnumerator(Session, Func);
+  }
+
+private:
+  typedef std::vector<std::unique_ptr<PDBSymbolData>> ArgListType;
+  const IPDBSession &Session;
+  const PDBSymbolFunc &Func;
+  ArgListType Args;
+  ArgListType::const_iterator CurIter;
+};
+}
+
 PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession,
                              std::unique_ptr<IPDBRawSymbol> Symbol)
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
@@ -24,6 +89,15 @@
   return Session.getConcreteSymbolById<PDBSymbolTypeFunctionSig>(getTypeId());
 }
 
+std::unique_ptr<IPDBEnumChildren<PDBSymbolData>>
+PDBSymbolFunc::getArguments() const {
+  return llvm::make_unique<FunctionArgEnumerator>(Session, *this);
+}
+
+std::unique_ptr<PDBSymbolTypeUDT> PDBSymbolFunc::getClassParent() const {
+  return Session.getConcreteSymbolById<PDBSymbolTypeUDT>(getClassParentId());
+}
+
 void PDBSymbolFunc::dump(raw_ostream &OS, int Indent,
                          PDBSymDumper &Dumper) const {
   Dumper.dump(*this, OS, Indent);
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
index 1759bd8..ffe6c80 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
@@ -9,6 +9,7 @@
 
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
 
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
 #include "llvm/DebugInfo/PDB/PDBSymDumper.h"
 
 #include <utility>
@@ -19,6 +20,10 @@
                                        std::unique_ptr<IPDBRawSymbol> Symbol)
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
+std::unique_ptr<PDBSymbol> PDBSymbolTypeArray::getElementType() const {
+  return Session.getSymbolById(getTypeId());
+}
+
 void PDBSymbolTypeArray::dump(raw_ostream &OS, int Indent,
                               PDBSymDumper &Dumper) const {
   Dumper.dump(*this, OS, Indent);
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
index cac23f7..d274bf5 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
@@ -9,6 +9,7 @@
 
 #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
 
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
 #include "llvm/DebugInfo/PDB/PDBSymDumper.h"
 
 #include <utility>
@@ -19,6 +20,10 @@
     const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
+std::unique_ptr<PDBSymbol> PDBSymbolTypePointer::getPointeeType() const {
+  return Session.getSymbolById(getTypeId());
+}
+
 void PDBSymbolTypePointer::dump(raw_ostream &OS, int Indent,
                                 PDBSymDumper &Dumper) const {
   Dumper.dump(*this, OS, Indent);