zturner created this revision.
zturner added reviewers: aleksandr.urakov, amccarth, lemo, labath.
Herald added a subscriber: aprantl.

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.

After this patch, I think most of the remaining DIA PDB tests can be re-written 
as native PDB tests, so hopefully this means we cane eliminate the DIA reader 
quite soon.


https://reviews.llvm.org/D56461

Files:
  lldb/include/lldb/Symbol/CompileUnit.h
  lldb/lit/SymbolFile/NativePDB/typedefs.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
  lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
  lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h

Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -203,12 +203,14 @@
   lldb::VariableSP GetOrCreateLocalVariable(PdbCompilandSymId scope_id,
                                             PdbCompilandSymId var_id,
                                             bool is_param);
+  lldb::TypeSP GetOrCreateTypedef(PdbGlobalSymId id);
 
   lldb::FunctionSP CreateFunction(PdbCompilandSymId func_id,
                                   CompileUnit &comp_unit);
   Block &CreateBlock(PdbCompilandSymId block_id);
   lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id,
                                        PdbCompilandSymId var_id, bool is_param);
+  lldb::TypeSP CreateTypedef(PdbGlobalSymId id);
   lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci);
   lldb::TypeSP CreateType(PdbTypeSymId type_id, CompilerType ct);
   lldb::TypeSP CreateAndCacheType(PdbTypeSymId type_id);
@@ -222,6 +224,7 @@
   llvm::BumpPtrAllocator m_allocator;
 
   lldb::addr_t m_obj_load_address = 0;
+  bool m_done_full_type_scan = false;
 
   std::unique_ptr<PdbIndex> m_index;
 
Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ 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;
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
@@ -66,6 +66,14 @@
     return cvunion;
   }
 
+  llvm::StringRef name() const {
+    if (m_kind == Struct || m_kind == Union)
+      return cvclass.Name;
+    if (m_kind == Enum)
+      return cvenum.Name;
+    return cvunion.Name;
+  }
+
 private:
   CVTagRecord(llvm::codeview::ClassRecord &&c);
   CVTagRecord(llvm::codeview::UnionRecord &&u);
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
@@ -17,8 +17,8 @@
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
 
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
 #include "lldb/Utility/LLDBAssert.h"
-
 #include "lldb/lldb-enumerations.h"
 
 using namespace lldb_private;
@@ -449,16 +449,7 @@
 }
 
 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
-  // Not all PDB names can be parsed with CPlusPlusNameParser.
-  // E.g. it fails on names containing `anonymous namespace'.
-  // So we simply drop everything before '::'
-
-  auto offset = name.rfind("::");
-  if (offset == llvm::StringRef::npos)
-    return name;
-  assert(offset + 2 <= name.size());
-
-  return name.substr(offset + 2);
+  return MSVCUndecoratedNameParser::DropScope(name);
 }
 
 VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
@@ -558,10 +549,6 @@
       result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
     } else {
       // FIXME: Handle other kinds
-      llvm::APSInt value;
-      value = 42;
-      result.location = MakeConstantLocationExpression(
-          TypeIndex::Int32(), index.tpi(), value, module);
     }
     return result;
   }
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
@@ -69,6 +69,7 @@
   clang::VarDecl *GetOrCreateVariableDecl(PdbCompilandSymId scope_id,
                                           PdbCompilandSymId var_id);
   clang::VarDecl *GetOrCreateVariableDecl(PdbGlobalSymId var_id);
+  clang::TypedefNameDecl *GetOrCreateTypedefDecl(PdbGlobalSymId id);
   void ParseDeclsForContext(clang::DeclContext &context);
 
   clang::QualType GetBasicType(lldb::BasicType type);
@@ -112,6 +113,8 @@
   clang::VarDecl *CreateVariableDecl(PdbSymUid uid,
                                      llvm::codeview::CVSymbol sym,
                                      clang::DeclContext &scope);
+  clang::DeclContext *
+  GetParentDeclContextForSymbol(const llvm::codeview::CVSymbol &sym);
 
   void ParseAllNamespacesPlusChildrenOf(llvm::Optional<llvm::StringRef> parent);
   void ParseDeclsForSimpleContext(clang::DeclContext &context);
@@ -120,6 +123,8 @@
   void BuildParentMap();
   std::pair<clang::DeclContext *, std::string>
   CreateDeclInfoForType(const llvm::codeview::TagRecord &record, TypeIndex ti);
+  std::pair<clang::DeclContext *, std::string>
+  CreateDeclInfoForUndecoratedName(llvm::StringRef uname);
   clang::QualType CreateSimpleType(TypeIndex ti);
 
   PdbIndex &m_index;
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -2,6 +2,7 @@
 
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
@@ -13,6 +14,7 @@
 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
 #include "llvm/Demangle/MicrosoftDemangle.h"
 
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/ClangExternalASTSourceCommon.h"
@@ -215,10 +217,15 @@
 std::pair<clang::DeclContext *, std::string>
 PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
   // FIXME: Move this to GetDeclContextContainingUID.
+  if (!record.hasUniqueName())
+    return CreateDeclInfoForUndecoratedName(record.Name);
 
   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 {m_clang.GetTranslationUnitDecl(), record.UniqueName};
+
   llvm::ms_demangle::IdentifierNode *idn =
       ttn->QualifiedName->getUnqualifiedIdentifier();
   std::string uname = idn->toString(llvm::ms_demangle::OF_NoTagSpecifier);
@@ -508,6 +515,82 @@
   return clang::Decl::castToDeclContext(decl);
 }
 
+std::pair<clang::DeclContext *, std::string>
+PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) {
+  MSVCUndecoratedNameParser parser(name);
+  llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+
+  clang::DeclContext *context = &GetTranslationUnitDecl();
+
+  llvm::StringRef uname = specs.back().GetBaseName();
+  specs = specs.drop_back();
+  if (specs.empty())
+    return {context, name};
+
+  llvm::StringRef scope_name = specs.back().GetFullName();
+
+  // It might be a class name, try that first.
+  std::vector<TypeIndex> types = m_index.tpi().findRecordsByName(scope_name);
+  while (!types.empty()) {
+    clang::QualType qt = GetOrCreateType(types.back());
+    clang::TagDecl *tag = qt->getAsTagDecl();
+    if (tag)
+      return {clang::TagDecl::castToDeclContext(tag), uname};
+    types.pop_back();
+  }
+
+  // If that fails, treat it as a series of namespaces.
+  for (const MSVCUndecoratedNameSpecifier &spec : specs) {
+    std::string ns_name = spec.GetBaseName().str();
+    context = m_clang.GetUniqueNamespaceDeclaration(ns_name.c_str(), context);
+  }
+  return {context, uname};
+}
+
+clang::DeclContext *
+PdbAstBuilder::GetParentDeclContextForSymbol(const CVSymbol &sym) {
+  if (!SymbolHasAddress(sym))
+    return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;
+  SegmentOffset addr = GetSegmentAndOffset(sym);
+  llvm::Optional<PublicSym32> pub =
+      FindPublicSym(addr, m_index.symrecords(), m_index.publics());
+  if (!pub)
+    return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;
+
+  llvm::ms_demangle::Demangler demangler;
+  StringView name{pub->Name.begin(), pub->Name.size()};
+  llvm::ms_demangle::SymbolNode *node = demangler.parse(name);
+  if (!node)
+    return &GetTranslationUnitDecl();
+  llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{
+      node->Name->Components->Nodes, node->Name->Components->Count - 1};
+
+  if (!name_components.empty()) {
+    // Render the current list of scope nodes as a fully qualified name, and
+    // look it up in the debug info as a type name.  If we find something,
+    // this is a type (which may itself be prefixed by a namespace).  If we
+    // don't, this is a list of namespaces.
+    std::string qname = RenderScopeList(name_components);
+    std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname);
+    while (!matches.empty()) {
+      clang::QualType qt = GetOrCreateType(matches.back());
+      clang::TagDecl *tag = qt->getAsTagDecl();
+      if (tag)
+        return clang::TagDecl::castToDeclContext(tag);
+      matches.pop_back();
+    }
+  }
+
+  // It's not a type.  It must be a series of namespaces.
+  clang::DeclContext *context = &GetTranslationUnitDecl();
+  while (!name_components.empty()) {
+    std::string ns = name_components.front()->toString();
+    context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context);
+    name_components = name_components.drop_front();
+  }
+  return context;
+}
+
 clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
   // We must do this *without* calling GetOrCreate on the current uid, as
   // that would be an infinite recursion.
@@ -519,46 +602,7 @@
       return GetOrCreateDeclContextForUid(*scope);
 
     CVSymbol sym = m_index.ReadSymbolRecord(uid.asCompilandSym());
-    if (!SymbolHasAddress(sym))
-      return &GetTranslationUnitDecl();
-    SegmentOffset addr = GetSegmentAndOffset(sym);
-    llvm::Optional<PublicSym32> pub =
-        FindPublicSym(addr, m_index.symrecords(), m_index.publics());
-    if (!pub)
-      return &GetTranslationUnitDecl();
-
-    llvm::ms_demangle::Demangler demangler;
-    StringView name{pub->Name.begin(), pub->Name.size()};
-    llvm::ms_demangle::SymbolNode *node = demangler.parse(name);
-    if (!node)
-      return &GetTranslationUnitDecl();
-    llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{
-        node->Name->Components->Nodes, node->Name->Components->Count - 1};
-
-    if (!name_components.empty()) {
-      // Render the current list of scope nodes as a fully qualified name, and
-      // look it up in the debug info as a type name.  If we find something,
-      // this is a type (which may itself be prefixed by a namespace).  If we
-      // don't, this is a list of namespaces.
-      std::string qname = RenderScopeList(name_components);
-      std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname);
-      while (!matches.empty()) {
-        clang::QualType qt = GetOrCreateType(matches.back());
-        clang::TagDecl *tag = qt->getAsTagDecl();
-        if (tag)
-          return clang::TagDecl::castToDeclContext(tag);
-        matches.pop_back();
-      }
-    }
-
-    // It's not a type.  It must be a series of namespaces.
-    clang::DeclContext *context = &GetTranslationUnitDecl();
-    while (!name_components.empty()) {
-      std::string ns = name_components.front()->toString();
-      context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context);
-      name_components = name_components.drop_front();
-    }
-    return context;
+    return GetParentDeclContextForSymbol(sym);
   }
   case PdbSymUidKind::Type: {
     // It could be a namespace, class, or global.  We don't support nested
@@ -573,6 +617,34 @@
     // In this case the parent DeclContext is the one for the class that this
     // member is inside of.
     break;
+  case PdbSymUidKind::GlobalSym: {
+    // If this refers to a compiland symbol, just recurse in with that symbol.
+    // The only other possibilities are S_CONSTANT and S_UDT, in which case we
+    // need to parse the undecorated name to figure out the scope, then look
+    // that up in the TPI stream.  If it's found, it's a type, othewrise it's
+    // a series of namespaces.
+    // FIXME: do this.
+    CVSymbol global = m_index.ReadSymbolRecord(uid.asGlobalSym());
+    switch (global.kind()) {
+    case SymbolKind::S_GDATA32:
+    case SymbolKind::S_LDATA32:
+      return GetParentDeclContextForSymbol(global);
+    case SymbolKind::S_PROCREF:
+    case SymbolKind::S_LPROCREF: {
+      ProcRefSym ref{global.kind()};
+      llvm::cantFail(
+          SymbolDeserializer::deserializeAs<ProcRefSym>(global, ref));
+      PdbCompilandSymId cu_sym_id{ref.modi(), ref.SymOffset};
+      return GetParentDeclContext(cu_sym_id);
+    }
+    case SymbolKind::S_CONSTANT:
+    case SymbolKind::S_UDT:
+      return CreateDeclInfoForUndecoratedName(getSymbolName(global)).first;
+    default:
+      break;
+    }
+    break;
+  }
   default:
     break;
   }
@@ -662,6 +734,11 @@
 clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) {
   clang::QualType pointee_type = GetOrCreateType(pointer.ReferentType);
 
+  // This can happen for pointers to LF_VTSHAPE records, which we shouldn't
+  // create in the AST.
+  if (pointee_type.isNull())
+    return {};
+
   if (pointer.isPointerToMember()) {
     MemberPointerInfo mpi = pointer.getMemberInfo();
     clang::QualType class_type = GetOrCreateType(mpi.ContainingType);
@@ -694,8 +771,9 @@
 
 clang::QualType
 PdbAstBuilder::CreateModifierType(const ModifierRecord &modifier) {
-
   clang::QualType unmodified_type = GetOrCreateType(modifier.ModifiedType);
+  if (unmodified_type.isNull())
+    return {};
 
   if ((modifier.Modifiers & ModifierOptions::Const) != ModifierOptions::None)
     unmodified_type.addConst();
@@ -803,6 +881,32 @@
   return CreateVariableDecl(PdbSymUid(var_id), sym, GetTranslationUnitDecl());
 }
 
+clang::TypedefNameDecl *
+PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) {
+  if (clang::Decl *decl = TryGetDecl(id))
+    return llvm::dyn_cast<clang::TypedefNameDecl>(decl);
+
+  CVSymbol sym = m_index.ReadSymbolRecord(id);
+  lldbassert(sym.kind() == S_UDT);
+  UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
+
+  clang::DeclContext *scope = GetParentDeclContext(id);
+
+  PdbTypeSymId real_type_id{udt.Type, false};
+  clang::QualType qt = GetOrCreateType(real_type_id);
+
+  std::string uname = DropNameScope(udt.Name);
+
+  CompilerType ct = m_clang.CreateTypedefType(ToCompilerType(qt), uname.c_str(),
+                                              ToCompilerDeclContext(*scope));
+  clang::TypedefNameDecl *tnd = m_clang.GetAsTypedefDecl(ct);
+  DeclStatus status;
+  status.resolved = true;
+  status.uid = toOpaqueUid(id);
+  m_decl_to_status.insert({tnd, status});
+  return tnd;
+}
+
 clang::QualType PdbAstBuilder::GetBasicType(lldb::BasicType type) {
   CompilerType ct = m_clang.GetBasicType(type);
   return clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType());
Index: lldb/lit/SymbolFile/NativePDB/typedefs.cpp
===================================================================
--- /dev/null
+++ lldb/lit/SymbolFile/NativePDB/typedefs.cpp
@@ -0,0 +1,71 @@
+// clang-format off
+
+// REQUIRES: system-windows
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols -dump-ast %t.exe | FileCheck %s
+
+namespace A {
+  namespace B {
+    using NamespaceTypedef = double;
+  }
+  template<typename T>
+  class C {
+  public:
+    using ClassTypedef = T;
+  };
+  using ClassTypedef = C<char>::ClassTypedef;
+  using ClassTypedef2 = C<wchar_t>::ClassTypedef;
+  
+  template<typename T>
+  using AliasTemplate = typename C<T>::ClassTypedef;
+}
+
+namespace {
+  using AnonNamespaceTypedef = bool;
+}
+
+using IntTypedef = int;
+
+using ULongArrayTypedef = unsigned long[10];
+
+using RefTypedef = long double*&;
+
+using FuncPtrTypedef = long long(*)(int&, unsigned char**, short[], const double, volatile bool);
+
+using VarArgsFuncTypedef = char(*)(void*, long, unsigned short, unsigned int, ...);
+
+using VarArgsFuncTypedefA = float(*)(...);
+
+int main(int argc, char **argv) {
+  long double *Ptr;
+  
+  A::B::NamespaceTypedef *X0;
+  A::C<char>::ClassTypedef *X1;
+  A::C<wchar_t>::ClassTypedef *X2;
+  AnonNamespaceTypedef *X3;
+  IntTypedef *X4;
+  ULongArrayTypedef *X5;
+  RefTypedef X6 = Ptr;
+  FuncPtrTypedef X7;
+  VarArgsFuncTypedef X8;
+  VarArgsFuncTypedefA X9;
+  A::AliasTemplate<float> X10;
+  return 0;
+}
+
+
+// CHECK:      namespace `anonymous namespace' {
+// CHECK-NEXT:     typedef bool AnonNamespaceTypedef;
+// CHECK-NEXT: }
+// CHECK-NEXT: typedef unsigned long ULongArrayTypedef[10];
+// CHECK-NEXT: typedef double *&RefTypedef;
+// CHECK-NEXT: namespace A {
+// CHECK-NEXT:     namespace B {
+// CHECK-NEXT:         typedef double NamespaceTypedef;
+// CHECK-NEXT:     }
+// CHECK-NEXT:     typedef float AliasTemplate<float>;
+// CHECK-NEXT: }
+// CHECK-NEXT: typedef long long (*FuncPtrTypedef)(int &, unsigned char **, short *, const double, volatile bool);
+// CHECK-NEXT: typedef char (*VarArgsFuncTypedef)(void *, long, unsigned short, unsigned int, ...);
+// CHECK-NEXT: typedef float (*VarArgsFuncTypedefA)(...);
+// CHECK-NEXT: typedef int IntTypedef;
Index: lldb/include/lldb/Symbol/CompileUnit.h
===================================================================
--- lldb/include/lldb/Symbol/CompileUnit.h
+++ lldb/include/lldb/Symbol/CompileUnit.h
@@ -409,6 +409,11 @@
   //------------------------------------------------------------------
   bool GetIsOptimized();
 
+  //------------------------------------------------------------------
+  /// Returns the number of functions in this compile unit
+  //------------------------------------------------------------------
+  size_t GetNumFunctions() const { return m_functions_by_uid.size(); }
+
 protected:
   void *m_user_data; ///< User data for the SymbolFile parser to store
                      ///information into.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to