This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rL350888: [NativePDB] Add support for parsing typedef records. 
(authored by zturner, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D56461?vs=180759&id=181137#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56461/new/

https://reviews.llvm.org/D56461

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

Index: lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ lldb/trunk/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/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
+++ lldb/trunk/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/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ lldb/trunk/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/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
+++ lldb/trunk/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/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ lldb/trunk/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);
@@ -491,6 +498,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.
@@ -502,46 +585,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
@@ -556,6 +600,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;
   }
@@ -645,6 +717,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);
@@ -677,8 +754,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();
@@ -786,6 +864,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/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
===================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
+++ lldb/trunk/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/trunk/lit/SymbolFile/NativePDB/typedefs.cpp
===================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/typedefs.cpp
+++ lldb/trunk/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/trunk/include/lldb/Symbol/CompileUnit.h
===================================================================
--- lldb/trunk/include/lldb/Symbol/CompileUnit.h
+++ lldb/trunk/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