[Lldb-commits] [lldb] r348631 - [NativePDB] Reconstruct function declarations from debug info.

Zachary Turner via lldb-commits lldb-commits at lists.llvm.org
Fri Dec 7 11:34:02 PST 2018


Author: zturner
Date: Fri Dec  7 11:34:02 2018
New Revision: 348631

URL: http://llvm.org/viewvc/llvm-project?rev=348631&view=rev
Log:
[NativePDB] Reconstruct function declarations from debug info.

Previously we would create an lldb::Function object for each function
parsed, but we would not add these to the clang AST. This is a first
step towards getting local variable support working, as we first need an
AST decl so that when we create local variable entries, they have the
proper DeclContext.

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

Added:
    lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit
    lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-types.lldbinit
    lldb/trunk/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp
    lldb/trunk/lit/SymbolFile/NativePDB/ast-functions.cpp
    lldb/trunk/lit/SymbolFile/NativePDB/ast-types.cpp
Removed:
    lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-reconstruction.lldbinit
    lldb/trunk/lit/SymbolFile/NativePDB/ast-reconstruction.cpp
Modified:
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h

Added: lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit?rev=348631&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit Fri Dec  7 11:34:02 2018
@@ -0,0 +1,8 @@
+
+break set -n main
+break set -n static_fn
+break set -n varargs_fn
+
+target modules dump ast
+
+quit

Removed: lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-reconstruction.lldbinit
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-reconstruction.lldbinit?rev=348630&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-reconstruction.lldbinit (original)
+++ lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-reconstruction.lldbinit (removed)
@@ -1,20 +0,0 @@
-target variable TC
-target variable TS
-target variable TU
-target variable TE
-
-target variable ABCInt
-target variable ABCFloat
-target variable ABCVoid
-
-target variable AC0
-target variable ACNeg1
-
-target variable AC0D
-target variable ACNeg1D
-target variable AD
-target variable ADE
-
-target modules dump ast
-
-quit

Added: lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-types.lldbinit
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-types.lldbinit?rev=348631&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-types.lldbinit (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/Inputs/ast-types.lldbinit Fri Dec  7 11:34:02 2018
@@ -0,0 +1,20 @@
+target variable TC
+target variable TS
+target variable TU
+target variable TE
+
+target variable ABCInt
+target variable ABCFloat
+target variable ABCVoid
+
+target variable AC0
+target variable ACNeg1
+
+target variable AC0D
+target variable ACNeg1D
+target variable AD
+target variable ADE
+
+target modules dump ast
+
+quit

Added: lldb/trunk/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp?rev=348631&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp Fri Dec  7 11:34:02 2018
@@ -0,0 +1,7 @@
+// clang-format off
+// REQUIRES: msvc
+
+// RUN: %build --compiler=msvc --nodefaultlib -o %t.exe -- %S/ast-functions.cpp
+
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN:     %p/Inputs/ast-functions.lldbinit 2>&1 | FileCheck %S/ast-functions.cpp

Added: lldb/trunk/lit/SymbolFile/NativePDB/ast-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/ast-functions.cpp?rev=348631&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/ast-functions.cpp (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/ast-functions.cpp Fri Dec  7 11:34:02 2018
@@ -0,0 +1,29 @@
+// clang-format off
+// REQUIRES: lld
+
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN:     %p/Inputs/ast-functions.lldbinit 2>&1 | FileCheck %s
+
+static int static_fn() {
+  return 42;
+}
+
+int varargs_fn(int x, int y, ...) {
+  return x + y;
+}
+
+int main(int argc, char **argv) {
+  return static_fn() + varargs_fn(argc, argc);
+}
+
+// CHECK:      TranslationUnitDecl
+// CHECK-NEXT: |-FunctionDecl {{.*}} main 'int (int, char **)'
+// CHECK-NEXT: | |-ParmVarDecl {{.*}} argc 'int'
+// CHECK-NEXT: | `-ParmVarDecl {{.*}} argv 'char **'
+// CHECK-NEXT: |-FunctionDecl {{.*}} static_fn 'int ()' static
+// CHECK-NEXT: |-FunctionDecl {{.*}} varargs_fn 'int (int, int, ...)'
+// CHECK-NEXT: | |-ParmVarDecl {{.*}} x 'int'
+// CHECK-NEXT: | `-ParmVarDecl {{.*}} y 'int'
+// CHECK-NEXT: `-<undeserialized declarations>

Removed: lldb/trunk/lit/SymbolFile/NativePDB/ast-reconstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/ast-reconstruction.cpp?rev=348630&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/ast-reconstruction.cpp (original)
+++ lldb/trunk/lit/SymbolFile/NativePDB/ast-reconstruction.cpp (removed)
@@ -1,131 +0,0 @@
-// clang-format off
-// REQUIRES: lld
-
-// Test various interesting cases for AST reconstruction.
-// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
-// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
-// RUN:     %p/Inputs/ast-reconstruction.lldbinit 2>&1 | FileCheck %s
-
-// Test trivial versions of each tag type.
-class TrivialC {};
-struct TrivialS {};
-union TrivialU {};
-enum TrivialE {TE_A};
-
-// Test reconstruction of DeclContext hierarchies.
-namespace A {
-  namespace B {
-    template<typename T>
-    struct C {
-      T ABCMember;
-    };
-
-    // Let's try a template specialization with a different implementation
-    template<>
-    struct C<void> {
-      void *ABCSpecializationMember;
-    };
-  }
-
-  // Let's make sure we can distinguish classes and namespaces.  Also let's try
-  // a non-type template parameter.
-  template<int N>
-  struct C {
-    class D {
-      int ACDMember = 0;
-      C<N - 1> *CPtr = nullptr;
-    };
-  };
-
-  struct D {
-    // Let's make a nested class with the same name as another nested class
-    // elsewhere, and confirm that they appear in the right DeclContexts in
-    // the AST.
-    struct E {
-      int ADDMember;
-    };
-  };
-}
-
-
-// Let's try an anonymous namespace.
-namespace {
-  template<typename T>
-  struct Anonymous {
-    int AnonymousMember;
-    // And a nested class within an anonymous namespace
-    struct D {
-      int AnonymousDMember;
-    };
-  };
-}
-
-TrivialC TC;
-TrivialS TS;
-TrivialU TU;
-TrivialE TE;
-
-A::B::C<int> ABCInt;
-A::B::C<float> ABCFloat;
-A::B::C<void> ABCVoid;
-
-A::C<0> AC0;
-A::C<-1> ACNeg1;
-
-A::C<0>::D AC0D;
-A::C<-1>::D ACNeg1D;
-A::D AD;
-A::D::E ADE;
-
-// FIXME: Anonymous namespaces aren't working correctly.
-Anonymous<int> AnonInt;
-Anonymous<A::B::C<void>> AnonABCVoid;
-Anonymous<A::B::C<int>>::D AnonABCVoidD;
-
-// FIXME: Enum size isn't being correctly determined.
-// FIXME: Can't read memory for variable values.
-
-// CHECK: (TrivialC) TC = {}
-// CHECK: (TrivialS) TS = {}
-// CHECK: (TrivialU) TU = {}
-// CHECK: (TrivialE) TE = TE_A
-// CHECK: (A::B::C<int>) ABCInt = (ABCMember = 0)
-// CHECK: (A::B::C<float>) ABCFloat = (ABCMember = 0)
-// CHECK: (A::B::C<void>) ABCVoid = (ABCSpecializationMember = 0x{{0+}})
-// CHECK: (A::C<0>) AC0 = {}
-// CHECK: (A::C<-1>) ACNeg1 = {}
-// CHECK: (A::C<0>::D) AC0D = (ACDMember = 0, CPtr = 0x{{0+}})
-// CHECK: (A::C<-1>::D) ACNeg1D = (ACDMember = 0, CPtr = 0x{{0+}})
-// CHECK: (A::D) AD = {}
-// CHECK: (A::D::E) ADE = (ADDMember = 0)
-// CHECK: Dumping clang ast for 1 modules.
-// CHECK: TranslationUnitDecl {{.*}}
-// CHECK: |-CXXRecordDecl {{.*}} class TrivialC definition
-// CHECK: |-CXXRecordDecl {{.*}} struct TrivialS definition
-// CHECK: |-CXXRecordDecl {{.*}} union TrivialU definition
-// CHECK: |-EnumDecl {{.*}} TrivialE
-// CHECK: | `-EnumConstantDecl {{.*}} TE_A 'TrivialE'
-// CHECK: |-NamespaceDecl {{.*}} A
-// CHECK: | |-NamespaceDecl {{.*}} B
-// CHECK: | | |-CXXRecordDecl {{.*}} struct C<int> definition
-// CHECK: | | | `-FieldDecl {{.*}} ABCMember 'int'
-// CHECK: | | |-CXXRecordDecl {{.*}} struct C<float> definition
-// CHECK: | | | `-FieldDecl {{.*}} ABCMember 'float'
-// CHECK: | | `-CXXRecordDecl {{.*}} struct C<void> definition
-// CHECK: | |   `-FieldDecl {{.*}} ABCSpecializationMember 'void *'
-// CHECK: | |-CXXRecordDecl {{.*}} struct C<0> definition
-// CHECK: | | `-CXXRecordDecl {{.*}} class D definition
-// CHECK: | |   |-FieldDecl {{.*}} ACDMember 'int'
-// CHECK: | |   `-FieldDecl {{.*}} CPtr 'A::C<-1> *'
-// CHECK: | |-CXXRecordDecl {{.*}} struct C<-1> definition
-// CHECK: | | `-CXXRecordDecl {{.*}} class D definition
-// CHECK: | |   |-FieldDecl {{.*}} ACDMember 'int'
-// CHECK: | |   `-FieldDecl {{.*}} CPtr 'A::C<-2> *'
-// CHECK: | |-CXXRecordDecl {{.*}} struct C<-2>
-// CHECK: | `-CXXRecordDecl {{.*}} struct D definition
-// CHECK: |   `-CXXRecordDecl {{.*}} struct E definition
-// CHECK: |     `-FieldDecl {{.*}} ADDMember 'int'
-
-int main(int argc, char **argv) {
-  return 0;
-}

Added: lldb/trunk/lit/SymbolFile/NativePDB/ast-types.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/ast-types.cpp?rev=348631&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/ast-types.cpp (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/ast-types.cpp Fri Dec  7 11:34:02 2018
@@ -0,0 +1,131 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test various interesting cases for AST reconstruction.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN:     %p/Inputs/ast-types.lldbinit 2>&1 | FileCheck %s
+
+// Test trivial versions of each tag type.
+class TrivialC {};
+struct TrivialS {};
+union TrivialU {};
+enum TrivialE {TE_A};
+
+// Test reconstruction of DeclContext hierarchies.
+namespace A {
+  namespace B {
+    template<typename T>
+    struct C {
+      T ABCMember;
+    };
+
+    // Let's try a template specialization with a different implementation
+    template<>
+    struct C<void> {
+      void *ABCSpecializationMember;
+    };
+  }
+
+  // Let's make sure we can distinguish classes and namespaces.  Also let's try
+  // a non-type template parameter.
+  template<int N>
+  struct C {
+    class D {
+      int ACDMember = 0;
+      C<N - 1> *CPtr = nullptr;
+    };
+  };
+
+  struct D {
+    // Let's make a nested class with the same name as another nested class
+    // elsewhere, and confirm that they appear in the right DeclContexts in
+    // the AST.
+    struct E {
+      int ADDMember;
+    };
+  };
+}
+
+
+// Let's try an anonymous namespace.
+namespace {
+  template<typename T>
+  struct Anonymous {
+    int AnonymousMember;
+    // And a nested class within an anonymous namespace
+    struct D {
+      int AnonymousDMember;
+    };
+  };
+}
+
+TrivialC TC;
+TrivialS TS;
+TrivialU TU;
+TrivialE TE;
+
+A::B::C<int> ABCInt;
+A::B::C<float> ABCFloat;
+A::B::C<void> ABCVoid;
+
+A::C<0> AC0;
+A::C<-1> ACNeg1;
+
+A::C<0>::D AC0D;
+A::C<-1>::D ACNeg1D;
+A::D AD;
+A::D::E ADE;
+
+// FIXME: Anonymous namespaces aren't working correctly.
+Anonymous<int> AnonInt;
+Anonymous<A::B::C<void>> AnonABCVoid;
+Anonymous<A::B::C<int>>::D AnonABCVoidD;
+
+// FIXME: Enum size isn't being correctly determined.
+// FIXME: Can't read memory for variable values.
+
+// CHECK: (TrivialC) TC = {}
+// CHECK: (TrivialS) TS = {}
+// CHECK: (TrivialU) TU = {}
+// CHECK: (TrivialE) TE = TE_A
+// CHECK: (A::B::C<int>) ABCInt = (ABCMember = 0)
+// CHECK: (A::B::C<float>) ABCFloat = (ABCMember = 0)
+// CHECK: (A::B::C<void>) ABCVoid = (ABCSpecializationMember = 0x{{0+}})
+// CHECK: (A::C<0>) AC0 = {}
+// CHECK: (A::C<-1>) ACNeg1 = {}
+// CHECK: (A::C<0>::D) AC0D = (ACDMember = 0, CPtr = 0x{{0+}})
+// CHECK: (A::C<-1>::D) ACNeg1D = (ACDMember = 0, CPtr = 0x{{0+}})
+// CHECK: (A::D) AD = {}
+// CHECK: (A::D::E) ADE = (ADDMember = 0)
+// CHECK: Dumping clang ast for 1 modules.
+// CHECK: TranslationUnitDecl {{.*}}
+// CHECK: |-CXXRecordDecl {{.*}} class TrivialC definition
+// CHECK: |-CXXRecordDecl {{.*}} struct TrivialS definition
+// CHECK: |-CXXRecordDecl {{.*}} union TrivialU definition
+// CHECK: |-EnumDecl {{.*}} TrivialE
+// CHECK: | `-EnumConstantDecl {{.*}} TE_A 'TrivialE'
+// CHECK: |-NamespaceDecl {{.*}} A
+// CHECK: | |-NamespaceDecl {{.*}} B
+// CHECK: | | |-CXXRecordDecl {{.*}} struct C<int> definition
+// CHECK: | | | `-FieldDecl {{.*}} ABCMember 'int'
+// CHECK: | | |-CXXRecordDecl {{.*}} struct C<float> definition
+// CHECK: | | | `-FieldDecl {{.*}} ABCMember 'float'
+// CHECK: | | `-CXXRecordDecl {{.*}} struct C<void> definition
+// CHECK: | |   `-FieldDecl {{.*}} ABCSpecializationMember 'void *'
+// CHECK: | |-CXXRecordDecl {{.*}} struct C<0> definition
+// CHECK: | | `-CXXRecordDecl {{.*}} class D definition
+// CHECK: | |   |-FieldDecl {{.*}} ACDMember 'int'
+// CHECK: | |   `-FieldDecl {{.*}} CPtr 'A::C<-1> *'
+// CHECK: | |-CXXRecordDecl {{.*}} struct C<-1> definition
+// CHECK: | | `-CXXRecordDecl {{.*}} class D definition
+// CHECK: | |   |-FieldDecl {{.*}} ACDMember 'int'
+// CHECK: | |   `-FieldDecl {{.*}} CPtr 'A::C<-2> *'
+// CHECK: | |-CXXRecordDecl {{.*}} struct C<-2>
+// CHECK: | `-CXXRecordDecl {{.*}} struct D definition
+// CHECK: |   `-CXXRecordDecl {{.*}} struct E definition
+// CHECK: |     `-FieldDecl {{.*}} ADDMember 'int'
+
+int main(int argc, char **argv) {
+  return 0;
+}

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp?rev=348631&r1=348630&r2=348631&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp Fri Dec  7 11:34:02 2018
@@ -37,6 +37,7 @@
 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
 #include "llvm/DebugInfo/CodeView/RecordName.h"
 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
@@ -538,16 +539,114 @@ lldb::FunctionSP SymbolFileNativePDB::Cr
   if (!func_range.GetBaseAddress().IsValid())
     return nullptr;
 
-  Type *func_type = nullptr;
+  ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
+  cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
+  TypeSP func_type = GetOrCreateType(proc.FunctionType);
 
-  // FIXME: Resolve types and mangled names.
-  PdbTypeSymId sig_id(TypeIndex::None(), false);
-  Mangled mangled(getSymbolName(sym_record));
+  PdbTypeSymId sig_id(proc.FunctionType, false);
+  Mangled mangled(proc.Name);
   FunctionSP func_sp = std::make_shared<Function>(
       sc.comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
-      func_type, func_range);
+      func_type.get(), func_range);
 
   sc.comp_unit->AddFunction(func_sp);
+
+  clang::StorageClass storage = clang::SC_None;
+  if (sym_record.kind() == S_LPROC32)
+    storage = clang::SC_Static;
+
+  // There are two ways we could retrieve the parameter list.  The first is by
+  // iterating the arguments on the function signature type, however that would
+  // only tell us the types of the arguments and not the names.  The second is
+  // to iterate the CVSymbol records that follow the S_GPROC32 / S_LPROC32 until
+  // we have the correct number of arguments as stated by the function
+  // signature. The latter has more potential to go wrong in the face of
+  // improper debug info simply because we're assuming more about the layout of
+  // the records, but it is the only way to get argument names.
+  CVType sig_cvt;
+  CVType arg_list_cvt;
+  ProcedureRecord sig_record;
+  ArgListRecord arg_list_record;
+
+  sig_cvt = m_index->tpi().getType(proc.FunctionType);
+  if (sig_cvt.kind() != LF_PROCEDURE)
+    return func_sp;
+  cantFail(
+      TypeDeserializer::deserializeAs<ProcedureRecord>(sig_cvt, sig_record));
+
+  CompilerDeclContext context =
+      GetDeclContextContainingUID(toOpaqueUid(func_id));
+
+  clang::DeclContext *decl_context =
+      static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext());
+  clang::FunctionDecl *function_decl = m_clang->CreateFunctionDeclaration(
+      decl_context, proc.Name.str().c_str(),
+      func_type->GetForwardCompilerType(), storage, false);
+
+  lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0);
+  m_uid_to_decl[toOpaqueUid(func_id)] = function_decl;
+  CVSymbolArray scope = limitSymbolArrayToScope(
+      cci->m_debug_stream.getSymbolArray(), func_id.offset);
+
+  uint32_t params_remaining = sig_record.getParameterCount();
+  auto begin = scope.begin();
+  auto end = scope.end();
+  std::vector<clang::ParmVarDecl *> params;
+  while (begin != end && params_remaining > 0) {
+    uint32_t record_offset = begin.offset();
+    CVSymbol sym = *begin++;
+
+    TypeIndex param_type;
+    llvm::StringRef param_name;
+    switch (sym.kind()) {
+    case S_REGREL32: {
+      RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
+      cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
+      param_type = reg.Type;
+      param_name = reg.Name;
+      break;
+    }
+    case S_REGISTER: {
+      RegisterSym reg(SymbolRecordKind::RegisterSym);
+      cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
+      param_type = reg.Index;
+      param_name = reg.Name;
+      break;
+    }
+    case S_LOCAL: {
+      LocalSym local(SymbolRecordKind::LocalSym);
+      cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+      if ((local.Flags & LocalSymFlags::IsParameter) == LocalSymFlags::None)
+        continue;
+      param_type = local.Type;
+      param_name = local.Name;
+      break;
+    }
+    case S_BLOCK32:
+      // All parameters should come before the first block.  If that isn't the
+      // case, then perhaps this is bad debug info that doesn't contain
+      // information about all parameters.
+      params_remaining = 0;
+      continue;
+    default:
+      continue;
+    }
+
+    PdbCompilandSymId param_uid(func_id.modi, record_offset);
+    TypeSP type_sp = GetOrCreateType(param_type);
+    clang::ParmVarDecl *param = m_clang->CreateParameterDeclaration(
+        param_name.str().c_str(), type_sp->GetForwardCompilerType(),
+        clang::SC_None);
+    lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0);
+
+    m_uid_to_decl[toOpaqueUid(param_uid)] = param;
+    params.push_back(param);
+    --params_remaining;
+  }
+
+  if (!params.empty())
+    m_clang->SetFunctionParameters(function_decl, params.data(), params.size());
+
   return func_sp;
 }
 
@@ -714,6 +813,8 @@ AnyScopesHaveTemplateParams(llvm::ArrayR
 std::pair<clang::DeclContext *, std::string>
 SymbolFileNativePDB::CreateDeclInfoForType(const TagRecord &record,
                                            TypeIndex ti) {
+  // FIXME: Move this to GetDeclContextContainingUID.
+
   llvm::ms_demangle::Demangler demangler;
   StringView sv(record.UniqueName.begin(), record.UniqueName.size());
   llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
@@ -1520,6 +1621,32 @@ size_t SymbolFileNativePDB::FindTypesByN
 
 size_t SymbolFileNativePDB::ParseTypes(const SymbolContext &sc) { return 0; }
 
+CompilerDeclContext
+SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
+  // FIXME: This should look up the uid, decide if it's a symbol or a type, and
+  // depending which it is, find the appropriate DeclContext.  Possibilities:
+  // For classes and typedefs:
+  //   * Function
+  //   * Namespace
+  //   * Global
+  //   * Block
+  //   * Class
+  // For field list members:
+  //   * Class
+  // For variables:
+  //   * Function
+  //   * Namespace
+  //   * Global
+  //   * Block
+  // For functions:
+  //   * Namespace
+  //   * Global
+  //   * Class
+  //
+  // It is an error to call this function with a uid for any other symbol type.
+  return {m_clang, m_clang->GetTranslationUnitDecl()};
+}
+
 Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
   auto iter = m_types.find(type_uid);
   // lldb should not be passing us non-sensical type uids.  the only way it

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h?rev=348631&r1=348630&r2=348631&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h Fri Dec  7 11:34:02 2018
@@ -112,6 +112,8 @@ public:
   size_t ParseVariablesForContext(const SymbolContext &sc) override {
     return 0;
   }
+
+  CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override;
   Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
   llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
       lldb::user_id_t type_uid,
@@ -217,7 +219,7 @@ private:
 
   llvm::DenseMap<clang::TagDecl *, DeclStatus> m_decl_to_status;
 
-  llvm::DenseMap<lldb::user_id_t, clang::TagDecl *> m_uid_to_decl;
+  llvm::DenseMap<lldb::user_id_t, clang::Decl *> m_uid_to_decl;
   llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex>
       m_parent_types;
 




More information about the lldb-commits mailing list