[NativePDB] Add support for parsing typedef records.

Typedefs are represented as S_UDT records in the globals stream. This
creates a strange situation where "types" are actually represented as
"symbols", so they need special handling.

In order to test this, we don't just use lldb and print out some
variables causing the AST to get created, because variables whose type
is a typedef will have debug info referencing the original type, not the
typedef. So we use lldb-test instead which will parse all debug info in
the entire file. This exposed some problems with lldb-test and the
native reader, mainly that certain types of obscure symbols which we can
find when iterating every single record would trigger crashes. These
have been fixed as well so that lldb-test can be used to test this
functionality.

Differential Revision: https://reviews.llvm.org/D56461

llvm-svn: 350888
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 9868a32..2ac0b98 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -15,6 +15,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Type.h"
 
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/StreamBuffer.h"
@@ -394,7 +395,11 @@
 
   ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
   cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
+  if (proc.FunctionType == TypeIndex::None())
+    return nullptr;
   TypeSP func_type = GetOrCreateType(proc.FunctionType);
+  if (!func_type)
+    return nullptr;
 
   PdbTypeSymId sig_id(proc.FunctionType, false);
   Mangled mangled(proc.Name);
@@ -515,9 +520,19 @@
 }
 
 static std::string GetUnqualifiedTypeName(const TagRecord &record) {
+  if (!record.hasUniqueName()) {
+    MSVCUndecoratedNameParser parser(record.Name);
+    llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+
+    return specs.back().GetBaseName();
+  }
+
   llvm::ms_demangle::Demangler demangler;
   StringView sv(record.UniqueName.begin(), record.UniqueName.size());
   llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
+  if (demangler.Error)
+    return record.Name;
+
   llvm::ms_demangle::IdentifierNode *idn =
       ttn->QualifiedName->getUnqualifiedIdentifier();
   return idn->toString();
@@ -696,7 +711,10 @@
   if (iter != m_types.end())
     return iter->second;
 
-  return CreateAndCacheType(type_id);
+  TypeSP type = CreateAndCacheType(type_id);
+  if (type)
+    m_obj_file->GetModule()->GetTypeList()->Insert(type);
+  return type;
 }
 
 VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
@@ -821,7 +839,6 @@
   if (emplace_result.second)
     emplace_result.first->second = CreateFunction(func_id, comp_unit);
 
-  lldbassert(emplace_result.first->second);
   return emplace_result.first->second;
 }
 
@@ -887,7 +904,26 @@
 
 size_t SymbolFileNativePDB::ParseCompileUnitFunctions(const SymbolContext &sc) {
   lldbassert(sc.comp_unit);
-  return false;
+
+  PdbSymUid uid{sc.comp_unit->GetID()};
+  lldbassert(uid.kind() == PdbSymUidKind::Compiland);
+  uint16_t modi = uid.asCompiland().modi;
+  CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi);
+
+  size_t count = sc.comp_unit->GetNumFunctions();
+  const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
+  for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
+    if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32)
+      continue;
+
+    PdbCompilandSymId sym_id{modi, iter.offset()};
+
+    FunctionSP func = GetOrCreateFunction(sym_id, *sc.comp_unit);
+  }
+
+  size_t new_count = sc.comp_unit->GetNumFunctions();
+  lldbassert(new_count >= count);
+  return new_count - count;
 }
 
 static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {
@@ -1238,7 +1274,47 @@
   return match_count;
 }
 
-size_t SymbolFileNativePDB::ParseTypes(const SymbolContext &sc) { return 0; }
+size_t SymbolFileNativePDB::ParseTypes(const SymbolContext &sc) {
+  // Only do the full type scan the first time.
+  if (m_done_full_type_scan)
+    return 0;
+
+  size_t old_count = m_obj_file->GetModule()->GetTypeList()->GetSize();
+  LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
+
+  // First process the entire TPI stream.
+  for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
+    TypeSP type = GetOrCreateType(*ti);
+    if (type)
+      (void)type->GetFullCompilerType();
+  }
+
+  // Next look for S_UDT records in the globals stream.
+  for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
+    PdbGlobalSymId global{gid, false};
+    CVSymbol sym = m_index->ReadSymbolRecord(global);
+    if (sym.kind() != S_UDT)
+      continue;
+
+    UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
+    bool is_typedef = true;
+    if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) {
+      CVType cvt = m_index->tpi().getType(udt.Type);
+      llvm::StringRef name = CVTagRecord::create(cvt).name();
+      if (name == udt.Name)
+        is_typedef = false;
+    }
+
+    if (is_typedef)
+      GetOrCreateTypedef(global);
+  }
+
+  size_t new_count = m_obj_file->GetModule()->GetTypeList()->GetSize();
+
+  m_done_full_type_scan = true;
+
+  return new_count - old_count;
+}
 
 size_t
 SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,
@@ -1253,6 +1329,8 @@
                                                     bool is_param) {
   ModuleSP module = GetObjectFile()->GetModule();
   VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, module);
+  if (!var_info.location || !var_info.ranges)
+    return nullptr;
 
   CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
   CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
@@ -1285,6 +1363,32 @@
   return CreateLocalVariable(scope_id, var_id, is_param);
 }
 
+TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
+  CVSymbol sym = m_index->ReadSymbolRecord(id);
+  lldbassert(sym.kind() == SymbolKind::S_UDT);
+
+  UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
+
+  TypeSP target_type = GetOrCreateType(udt.Type);
+
+  (void)m_ast->GetOrCreateTypedefDecl(id);
+
+  Declaration decl;
+  return std::make_shared<lldb_private::Type>(
+      toOpaqueUid(id), this, ConstString(udt.Name), target_type->GetByteSize(),
+      nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID,
+      decl, target_type->GetForwardCompilerType(),
+      lldb_private::Type::eResolveStateForward);
+}
+
+TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {
+  auto iter = m_types.find(toOpaqueUid(id));
+  if (iter != m_types.end())
+    return iter->second;
+
+  return CreateTypedef(id);
+}
+
 size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
   Block &block = GetOrCreateBlock(block_id);
 
@@ -1349,7 +1453,8 @@
       variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param);
       if (is_param)
         --params_remaining;
-      variables->AddVariableIfUnique(variable);
+      if (variable)
+        variables->AddVariableIfUnique(variable);
       break;
     default:
       break;