[Lldb-commits] [lldb] r345848 - [NativePDB] Get LLDB types from PDB function types.

Zachary Turner via lldb-commits lldb-commits at lists.llvm.org
Thu Nov 1 09:37:29 PDT 2018


Author: zturner
Date: Thu Nov  1 09:37:29 2018
New Revision: 345848

URL: http://llvm.org/viewvc/llvm-project?rev=345848&view=rev
Log:
[NativePDB] Get LLDB types from PDB function types.

This adds basic support for getting function signature types
into LLDB's type system, including into clang's AST.  There are
a few edge cases which are not correctly handled, mostly dealing
with nested classes, but this isn't specific to functions and
apply equally to variable types.  Note that no attempt has been
made yet to deal with member function types, which will happen
in subsequent patches.

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

Added:
    lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-builtins.lldbinit
    lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-calling-conv.lldbinit
    lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-classes.lldbinit
    lldb/trunk/lit/SymbolFile/NativePDB/function-types-builtins.cpp
    lldb/trunk/lit/SymbolFile/NativePDB/function-types-calling-conv.cpp
    lldb/trunk/lit/SymbolFile/NativePDB/function-types-classes.cpp
Modified:
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h

Added: lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-builtins.lldbinit
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-builtins.lldbinit?rev=345848&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-builtins.lldbinit (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-builtins.lldbinit Thu Nov  1 09:37:29 2018
@@ -0,0 +1,70 @@
+command alias dv target variable
+
+dv aa
+dv ab
+dv ac
+dv ad
+dv ae
+dv af
+dv ag
+dv ah
+dv ai
+dv aj
+dv ak
+dv al
+dv am
+dv an
+dv ao
+dv aq
+dv ar
+dv as
+dv at
+dv au
+dv av
+dv aw
+dv ax
+dv ay
+dv az
+dv aaa
+dv aab
+dv aac
+dv aad
+dv ra
+dv rb
+dv rc
+dv rd
+dv re
+dv rf
+dv rg
+dv rh
+dv ri
+dv rj
+dv rk
+dv rl
+dv rm
+dv rn
+dv ro
+dv rq
+dv rr
+dv rs
+dv rt
+dv ru
+dv rv
+dv rw
+dv rx
+dv ry
+dv rz
+dv raa
+dv rab
+dv rac
+dv rad
+dv ref
+dv ref2
+dv ref3
+dv binp
+dv binr
+dv null
+dv rae
+dv aae
+
+quit

Added: lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-calling-conv.lldbinit
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-calling-conv.lldbinit?rev=345848&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-calling-conv.lldbinit (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-calling-conv.lldbinit Thu Nov  1 09:37:29 2018
@@ -0,0 +1,7 @@
+target variable sfn
+target variable ffn
+target variable tfn
+target variable cfn
+target variable vfn
+
+quit

Added: lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-classes.lldbinit
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-classes.lldbinit?rev=345848&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-classes.lldbinit (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/Inputs/function-types-classes.lldbinit Thu Nov  1 09:37:29 2018
@@ -0,0 +1,12 @@
+target variable a
+target variable b
+target variable c
+target variable d
+target variable e
+target variable f
+target variable g
+target variable h
+target variable i
+target variable incomplete
+
+quit

Added: lldb/trunk/lit/SymbolFile/NativePDB/function-types-builtins.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/function-types-builtins.cpp?rev=345848&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/function-types-builtins.cpp (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/function-types-builtins.cpp Thu Nov  1 09:37:29 2018
@@ -0,0 +1,215 @@
+// clang-format off
+// REQUIRES: lld
+
+// RUN: clang-cl /Z7 /GS- /GR- /c -Xclang -fkeep-static-consts /Fo%t.obj -- %s
+// RUN: lld-link /DEBUG /nodefaultlib /entry:main /OUT:%t.exe /PDB:%t.pdb -- %t.obj
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb -f %t.exe -s \
+// RUN:     %p/Inputs/function-types-builtins.lldbinit | FileCheck %s
+
+// Test that we can display function signatures with simple builtin
+// and pointer types.  We do this by using `target variable` in lldb
+// with global variables of type ptr-to-function or reference-to-function.
+// This technique in general allows us to exercise most of LLDB's type
+// system without a running process.
+
+template<typename T>
+struct MakeResult {
+  static T result() {
+    return T{};
+  }
+};
+
+template<typename T>
+struct MakeResult<T&> {
+  static T& result() {
+    static T t;
+    return t;
+  }
+};
+
+template<typename T>
+struct MakeResult<T&&> {
+  static T&& result() {
+    static T t;
+    return static_cast<T&&>(t);
+  }
+};
+
+
+void nullary() {}
+
+template<typename Arg>
+void unary(Arg) { }
+
+template<typename Ret, int N>
+Ret unaryret() { return MakeResult<Ret>::result(); }
+
+template<typename A1, typename A2>
+void binary(A1, A2) { }
+
+int varargs(int, int, ...) { return 0; }
+
+// Make sure to test every builtin type at least once for completeness.  We
+// test these in the globals-fundamentals.cpp when they are the types of
+// variables but it's possible to imagine a situation where things behave
+// differently as function arguments or return values than they do with
+// global variables.
+
+// some interesting cases with argument types.
+auto aa = &unary<bool>;
+// CHECK: (void (*)(bool)) aa = {{.*}}
+auto ab = &unary<char>;
+// CHECK: (void (*)(char)) ab = {{.*}}
+auto ac = &unary<signed char>;
+// CHECK: (void (*)(signed char)) ac = {{.*}}
+auto ad = &unary<unsigned char>;
+// CHECK: (void (*)(unsigned char)) ad = {{.*}}
+auto ae = &unary<char16_t>;
+// CHECK: (void (*)(char16_t)) ae = {{.*}}
+auto af = &unary<char32_t>;
+// CHECK: (void (*)(char32_t)) af = {{.*}}
+auto ag = &unary<wchar_t>;
+// CHECK: (void (*)(wchar_t)) ag = {{.*}}
+auto ah = &unary<short>;
+// CHECK: (void (*)(short)) ah = {{.*}}
+auto ai = &unary<unsigned short>;
+// CHECK: (void (*)(unsigned short)) ai = {{.*}}
+auto aj = &unary<int>;
+// CHECK: (void (*)(int)) aj = {{.*}}
+auto ak = &unary<unsigned int>;
+// CHECK: (void (*)(unsigned int)) ak = {{.*}}
+auto al = &unary<long>;
+// CHECK: (void (*)(long)) al = {{.*}}
+auto am = &unary<unsigned long>;
+// CHECK: (void (*)(unsigned long)) am = {{.*}}
+auto an = &unary<long long>;
+// CHECK: (void (*)(long long)) an = {{.*}}
+auto ao = &unary<unsigned long long>;
+// CHECK: (void (*)(unsigned long long)) ao = {{.*}}
+auto aq = &unary<float>;
+// CHECK: (void (*)(float)) aq = {{.*}}
+auto ar = &unary<double>;
+// CHECK: (void (*)(double)) ar = {{.*}}
+
+auto as = &unary<int*>;
+// CHECK: (void (*)(int *)) as = {{.*}}
+auto at = &unary<int**>;
+// CHECK: (void (*)(int **)) at = {{.*}}
+auto au = &unary<int&>;
+// CHECK: (void (*)(int &)) au = {{.*}}
+auto av = &unary<int&&>;
+// CHECK: (void (*)(int &&)) av = {{.*}}
+auto aw = &unary<const int*>;
+// CHECK: (void (*)(const int *)) aw = {{.*}}
+auto ax = &unary<volatile int*>;
+// CHECK: (void (*)(volatile int *)) ax = {{.*}}
+auto ay = &unary<const volatile int*>;
+// CHECK: (void (*)(const volatile int *)) ay = {{.*}}
+auto az = &unary<void*&>;
+// CHECK: (void (*)(void *&)) az = {{.*}}
+auto aaa = &unary<int(&)[5]>;
+// CHECK: (void (*)(int (&)[5])) aaa = {{.*}}
+auto aab = &unary<int(*)[5]>;
+// CHECK: (void (*)(int (*)[5])) aab = {{.*}}
+auto aac = &unary<int(&&)[5]>;
+// CHECK: (void (*)(int (&&)[5])) aac = {{.*}}
+auto aad = &unary<int(*const)[5]>;
+// CHECK: (void (*)(int (*)[5])) aad = {{.*}}
+
+
+// same test cases with return values, note we can't overload on return type
+// so we need to use a different instantiation each time.
+auto ra = &unaryret<bool, 0>;
+// CHECK: (bool (*)()) ra = {{.*}}
+auto rb = &unaryret<char, 1>;
+// CHECK: (char (*)()) rb = {{.*}}
+auto rc = &unaryret<signed char, 2>;
+// CHECK: (signed char (*)()) rc = {{.*}}
+auto rd = &unaryret<unsigned char, 3>;
+// CHECK: (unsigned char (*)()) rd = {{.*}}
+auto re = &unaryret<char16_t, 4>;
+// CHECK: (char16_t (*)()) re = {{.*}}
+auto rf = &unaryret<char32_t, 5>;
+// CHECK: (char32_t (*)()) rf = {{.*}}
+auto rg = &unaryret<wchar_t, 6>;
+// CHECK: (wchar_t (*)()) rg = {{.*}}
+auto rh = &unaryret<short, 7>;
+// CHECK: (short (*)()) rh = {{.*}}
+auto ri = &unaryret<unsigned short, 8>;
+// CHECK: (unsigned short (*)()) ri = {{.*}}
+auto rj = &unaryret<int, 9>;
+// CHECK: (int (*)()) rj = {{.*}}
+auto rk = &unaryret<unsigned int, 10>;
+// CHECK: (unsigned int (*)()) rk = {{.*}}
+auto rl = &unaryret<long, 11>;
+// CHECK: (long (*)()) rl = {{.*}}
+auto rm = &unaryret<unsigned long, 12>;
+// CHECK: (unsigned long (*)()) rm = {{.*}}
+auto rn = &unaryret<long long, 13>;
+// CHECK: (long long (*)()) rn = {{.*}}
+auto ro = &unaryret<unsigned long long, 14>;
+// CHECK: (unsigned long long (*)()) ro = {{.*}}
+auto rq = &unaryret<float, 15>;
+// CHECK: (float (*)()) rq = {{.*}}
+auto rr = &unaryret<double, 16>;
+// CHECK: (double (*)()) rr = {{.*}}
+
+auto rs = &unaryret<int*, 17>;
+// CHECK: (int *(*)()) rs = {{.*}}
+auto rt = &unaryret<int**, 18>;
+// CHECK: (int **(*)()) rt = {{.*}}
+auto ru = &unaryret<int&, 19>;
+// CHECK: (int &(*)()) ru = {{.*}}
+auto rv = &unaryret<int&&, 20>;
+// CHECK: (int &&(*)()) rv = {{.*}}
+auto rw = &unaryret<const int*, 21>;
+// CHECK: (const int *(*)()) rw = {{.*}}
+auto rx = &unaryret<volatile int*, 22>;
+// CHECK: (volatile int *(*)()) rx = {{.*}}
+auto ry = &unaryret<const volatile int*, 23>;
+// CHECK: (const volatile int *(*)()) ry = {{.*}}
+auto rz = &unaryret<void*&, 24>;
+// CHECK: (void *&(*)()) rz = {{.*}}
+
+// FIXME: This output doesn't really look correct.  It should probably be
+// formatting this as `int(&)[5] (*)()`.
+auto raa = &unaryret<int(&)[5], 25>;
+// CHECK: (int (&(*)())[5]) raa = {{.*}}
+auto rab = &unaryret<int(*)[5], 26>;
+// CHECK: (int (*(*)())[5]) rab = {{.*}}
+auto rac = &unaryret<int(&&)[5], 27>;
+// CHECK: (int (&&(*)())[5]) rac = {{.*}}
+auto rad = &unaryret<int(*const)[5], 28>;
+// CHECK: (int (*const (*)())[5]) rad = {{.*}}
+
+
+
+// Function references, we only need a couple of these since most of the
+// interesting cases are already tested.
+auto &ref = unary<bool>;
+// CHECK: (void (&)(bool)) ref = {{.*}} (&::ref = <Unable to determine byte size.>)
+auto &ref2 = unary<volatile int*>;
+// CHECK: (void (&)(volatile int *)) ref2 = {{.*}} (&::ref2 = <Unable to determine byte size.>)
+auto &ref3 = varargs;
+// CHECK: (int (&)(int, int, ...)) ref3 = {{.*}} (&::ref3 = <Unable to determine byte size.>)
+
+// Multiple arguments, as before, just something to make sure it works.
+auto binp = &binary<int*, const int*>;
+// CHECK: (void (*)(int *, const int *)) binp = {{.*}}
+auto &binr = binary<int*, const int*>;
+// CHECK: (void (&)(int *, const int *)) binr = {{.*}} (&::binr = <Unable to determine byte size.>)
+
+// And finally, a function with no arguments.
+auto null = &nullary;
+// CHECK: (void (*)()) null = {{.*}}
+
+// FIXME: These currently don't work because clang-cl emits incorrect debug info
+// for std::nullptr_t.  We should fix these in clang-cl.
+auto rae = &unaryret<decltype(nullptr), 29>;
+// CHECK: (nullptr_t (*)()) rae = {{.*}}
+auto aae = &unary<decltype(nullptr)>;
+// CHECK: (void (*)(nullptr_t)) aae = {{.*}}
+
+int main(int argc, char **argv) {
+  return 0;
+}

Added: lldb/trunk/lit/SymbolFile/NativePDB/function-types-calling-conv.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/function-types-calling-conv.cpp?rev=345848&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/function-types-calling-conv.cpp (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/function-types-calling-conv.cpp Thu Nov  1 09:37:29 2018
@@ -0,0 +1,33 @@
+// clang-format off
+// REQUIRES: lld
+
+// RUN: clang-cl -m32 /Z7 /GS- /GR- /c -Xclang -fkeep-static-consts /Fo%t.obj -- %s
+// RUN: lld-link /DEBUG /nodefaultlib /entry:main /OUT:%t.exe /PDB:%t.pdb -- %t.obj
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb -f %t.exe -s \
+// RUN:     %p/Inputs/function-types-calling-conv.lldbinit | FileCheck %s
+
+
+void __stdcall StdcallFn() {}
+void __fastcall FastcallFn() {}
+void __thiscall ThiscallFn() {}
+void __cdecl CdeclFn() {}
+void __vectorcall VectorcallFn() {}
+
+auto sfn = &StdcallFn;
+// CHECK: (void (*)() __attribute__((stdcall))) sfn = {{.*}}
+
+auto ffn = &FastcallFn;
+// CHECK: (void (*)() __attribute__((fastcall))) ffn = {{.*}}
+
+auto tfn = &ThiscallFn;
+// CHECK: (void (*)() __attribute__((thiscall))) tfn = {{.*}}
+
+auto cfn = &CdeclFn;
+// CHECK: (void (*)()) cfn = {{.*}}
+
+auto vfn = &VectorcallFn;
+// CHECK: (void (*)() __attribute__((vectorcall))) vfn = {{.*}}
+
+int main(int argc, char **argv) {
+  return 0;
+}
\ No newline at end of file

Added: lldb/trunk/lit/SymbolFile/NativePDB/function-types-classes.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/NativePDB/function-types-classes.cpp?rev=345848&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/NativePDB/function-types-classes.cpp (added)
+++ lldb/trunk/lit/SymbolFile/NativePDB/function-types-classes.cpp Thu Nov  1 09:37:29 2018
@@ -0,0 +1,118 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can display function signatures with class types.
+// RUN: clang-cl /Z7 /GS- /GR- /c -Xclang -fkeep-static-consts /Fo%t.obj -- %s
+// RUN: lld-link /DEBUG /nodefaultlib /entry:main /OUT:%t.exe /PDB:%t.pdb -- %t.obj
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb -f %t.exe -s \
+// RUN:     %p/Inputs/function-types-classes.lldbinit | FileCheck %s
+
+// This is just some unimportant helpers needed so that we can get reference and
+// rvalue-reference types into return values.
+template<typename T>
+struct MakeResult {
+  static T result() {
+    return T{};
+  }
+};
+
+template<typename T>
+struct MakeResult<T&> {
+  static T& result() {
+    static T t;
+    return t;
+  }
+};
+
+template<typename T>
+struct MakeResult<T&&> {
+  static T&& result() {
+    static T t;
+    return static_cast<T&&>(t);
+  }
+};
+
+
+template<typename R>
+R nullary() { return MakeResult<R>::result(); }
+
+template<typename R, typename A, typename B>
+R three(A a, B b) { return MakeResult<R>::result(); }
+
+template<typename R, typename A, typename B, typename C>
+R four(A a, B b, C c) { return MakeResult<R>::result(); }
+
+struct S {};
+class C {};
+union U {};
+enum E {};
+
+namespace A {
+  namespace B {
+    // NS::NS
+    struct S { };
+  }
+
+  struct C {
+    // NS::Struct
+    struct S {};
+  };
+}
+
+struct B {
+  struct A {
+    // Struct::Struct
+    struct S {};
+  };
+};
+
+template<typename T>
+struct TC {};
+
+// const and volatile modifiers
+auto a = &four<S, C*, U&, E&&>;
+// CHECK: (S (*)(C *, U &, E &&)) a = {{.*}}
+auto b = &four<E, const S*, const C&, const U&&>;
+// CHECK: (E (*)(const S *, const C &, const U &&)) b = {{.*}}
+auto c = &four<U, volatile E*, volatile S&, volatile C&&>;
+// CHECK: (U (*)(volatile E *, volatile S &, volatile C &&)) c = {{.*}}
+auto d = &four<C, const volatile U*, const volatile E&, const volatile S&&>;
+// CHECK: (C (*)(const volatile U *, const volatile E &, const volatile S &&)) d = {{.*}}
+
+// classes nested in namespaces and inner classes
+
+// FIXME: LLDB with native pdb plugin doesn't currently resolve nested names
+// correctly, because it requires creating clang::NamespaceDecl or
+// clang::RecordDecl for the outer namespace or classes.  PDB doesn't contain
+// sufficient information to distinguish namespace scopes from nested class
+// scopes, so the best we can hope for is a heuristic reconstruction of the
+// clang AST based on demangling the type's unique name.  However, this is
+// as-yet unimplemented in the native PDB plugin, so for now all of these will
+// all just look like `S` when LLDB prints them.
+auto e = &three<A::B::S*, B::A::S*, A::C::S&>;
+// CHECK: (S *(*)(S *, S &)) e = {{.*}}
+auto f = &three<A::C::S&, A::B::S*, B::A::S*>;
+// CHECK: (S &(*)(S *, S *)) f = {{.*}}
+auto g = &three<B::A::S*, A::C::S&, A::B::S*>;
+// CHECK: (S *(*)(S &, S *)) g = {{.*}}
+
+// parameter types that are themselves template instantiations.
+auto h = &four<TC<void>, TC<int>, TC<TC<int>>, TC<A::B::S>>;
+// Note the awkward space in TC<TC<int> >.  This is because this is how template
+// instantiations are emitted by the compiler, as the fully instantiated name.
+// Only via reconstruction of the AST through the mangled type name (see above
+// comment) can we hope to do better than this).
+// CHECK: (TC<void> (*)(TC<int>, TC<TC<int> >, S>)) h = {{.*}}
+
+auto i = &nullary<A::B::S>;
+// CHECK: (S (*)()) i = {{.*}}
+
+
+// Make sure we can handle types that don't have complete debug info.
+struct Incomplete;
+auto incomplete = &three<Incomplete*, Incomplete**, const Incomplete*>;
+// CHECK: (Incomplete *(*)(Incomplete **, const Incomplete *)) incomplete = {{.*}}
+
+int main(int argc, char **argv) {
+  return 0;
+}

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp?rev=345848&r1=345847&r2=345848&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp Thu Nov  1 09:37:29 2018
@@ -92,6 +92,8 @@ PDB_SymType lldb_private::npdb::CVTypeTo
     return PDB_SymType::PointerType;
   case LF_ENUM:
     return PDB_SymType::Enum;
+  case LF_PROCEDURE:
+    return PDB_SymType::FunctionSig;
   default:
     lldbassert(false && "Invalid type record kind!");
   }
@@ -361,4 +363,4 @@ llvm::StringRef lldb_private::npdb::Drop
   assert(offset + 2 <= name.size());
 
   return name.substr(offset + 2);
-}
\ No newline at end of file
+}

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=345848&r1=345847&r2=345848&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp Thu Nov  1 09:37:29 2018
@@ -49,6 +49,8 @@
 #include "llvm/Support/ErrorOr.h"
 #include "llvm/Support/MemoryBuffer.h"
 
+#include "Plugins/Language/CPlusPlus/CPlusPlusNameParser.h"
+
 #include "PdbSymUid.h"
 #include "PdbUtil.h"
 #include "UdtRecordCompleter.h"
@@ -394,6 +396,12 @@ static PDB_SymType GetPdbSymType(TpiStre
   return GetPdbSymType(tpi, LookThroughModifierRecord(cvt));
 }
 
+static bool IsCVarArgsFunction(llvm::ArrayRef<TypeIndex> args) {
+  if (args.empty())
+    return false;
+  return args.back() == TypeIndex::None();
+}
+
 static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) {
   switch (cr.Kind) {
   case TypeRecordKind::Class:
@@ -412,6 +420,32 @@ static clang::TagTypeKind TranslateUdtKi
   }
 }
 
+static llvm::Optional<clang::CallingConv>
+TranslateCallingConvention(llvm::codeview::CallingConvention conv) {
+  using CC = llvm::codeview::CallingConvention;
+  switch (conv) {
+
+  case CC::NearC:
+  case CC::FarC:
+    return clang::CallingConv::CC_C;
+  case CC::NearPascal:
+  case CC::FarPascal:
+    return clang::CallingConv::CC_X86Pascal;
+  case CC::NearFast:
+  case CC::FarFast:
+    return clang::CallingConv::CC_X86FastCall;
+  case CC::NearStdCall:
+  case CC::FarStdCall:
+    return clang::CallingConv::CC_X86StdCall;
+  case CC::ThisCall:
+    return clang::CallingConv::CC_X86ThisCall;
+  case CC::NearVector:
+    return clang::CallingConv::CC_X86VectorCall;
+  default:
+    return llvm::None;
+  }
+}
+
 void SymbolFileNativePDB::Initialize() {
   PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                 GetPluginDescriptionStatic(), CreateInstance,
@@ -540,7 +574,6 @@ lldb::FunctionSP SymbolFileNativePDB::Cr
   PdbSymUid sig_uid =
       PdbSymUid::makeTypeSymId(PDB_SymType::FunctionSig, TypeIndex{0}, false);
   Mangled mangled(getSymbolName(sym_record));
-
   FunctionSP func_sp = std::make_shared<Function>(
       sc.comp_unit, func_uid.toOpaqueId(), sig_uid.toOpaqueId(), mangled,
       func_type, func_range);
@@ -598,6 +631,8 @@ lldb::TypeSP SymbolFileNativePDB::Create
 lldb::TypeSP SymbolFileNativePDB::CreatePointerType(
     PdbSymUid type_uid, const llvm::codeview::PointerRecord &pr) {
   TypeSP pointee = GetOrCreateType(pr.ReferentType);
+  if (!pointee)
+    return nullptr;
   CompilerType pointee_ct = pointee->GetForwardCompilerType();
   lldbassert(pointee_ct);
   Declaration decl;
@@ -639,6 +674,17 @@ lldb::TypeSP SymbolFileNativePDB::Create
 }
 
 lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti) {
+  if (ti == TypeIndex::NullptrT()) {
+    PdbSymUid uid =
+        PdbSymUid::makeTypeSymId(PDB_SymType::BuiltinType, ti, false);
+    CompilerType ct = m_clang->GetBasicType(eBasicTypeNullPtr);
+    Declaration decl;
+    return std::make_shared<Type>(uid.toOpaqueId(), this,
+                                  ConstString("std::nullptr_t"), 0, nullptr,
+                                  LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
+                                  ct, Type::eResolveStateFull);
+  }
+
   if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
     PdbSymUid uid =
         PdbSymUid::makeTypeSymId(PDB_SymType::PointerType, ti, false);
@@ -670,7 +716,8 @@ lldb::TypeSP SymbolFileNativePDB::Create
     return nullptr;
 
   lldb::BasicType bt = GetCompilerTypeForSimpleKind(ti.getSimpleKind());
-  lldbassert(bt != lldb::eBasicTypeInvalid);
+  if (bt == lldb::eBasicTypeInvalid)
+    return nullptr;
   CompilerType ct = m_clang->GetBasicType(bt);
   size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());
 
@@ -687,10 +734,6 @@ lldb::TypeSP SymbolFileNativePDB::Create
     PdbSymUid type_uid, llvm::StringRef name, size_t size,
     clang::TagTypeKind ttk, clang::MSInheritanceAttr::Spelling inheritance) {
 
-  // Some UDT with trival ctor has zero length. Just ignore.
-  if (size == 0)
-    return nullptr;
-
   // Ignore unnamed-tag UDTs.
   name = DropNameScope(name);
   if (name.empty())
@@ -792,6 +835,49 @@ TypeSP SymbolFileNativePDB::CreateArrayT
   return array_sp;
 }
 
+TypeSP SymbolFileNativePDB::CreateProcedureType(PdbSymUid type_uid,
+                                                const ProcedureRecord &pr) {
+  TpiStream &stream = m_index->tpi();
+  CVType args_cvt = stream.getType(pr.ArgumentList);
+  ArgListRecord args;
+  llvm::cantFail(
+      TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args));
+
+  llvm::ArrayRef<TypeIndex> arg_indices = llvm::makeArrayRef(args.ArgIndices);
+  bool is_variadic = IsCVarArgsFunction(arg_indices);
+  if (is_variadic)
+    arg_indices = arg_indices.drop_back();
+
+  std::vector<CompilerType> arg_list;
+  arg_list.reserve(arg_list.size());
+
+  for (TypeIndex arg_index : arg_indices) {
+    TypeSP arg_sp = GetOrCreateType(arg_index);
+    if (!arg_sp)
+      return nullptr;
+    arg_list.push_back(arg_sp->GetFullCompilerType());
+  }
+
+  TypeSP return_type_sp = GetOrCreateType(pr.ReturnType);
+  if (!return_type_sp)
+    return nullptr;
+
+  llvm::Optional<clang::CallingConv> cc =
+      TranslateCallingConvention(pr.CallConv);
+  if (!cc)
+    return nullptr;
+
+  CompilerType return_ct = return_type_sp->GetFullCompilerType();
+  CompilerType func_sig_ast_type = m_clang->CreateFunctionType(
+      return_ct, arg_list.data(), arg_list.size(), is_variadic, 0, *cc);
+
+  Declaration decl;
+  return std::make_shared<lldb_private::Type>(
+      type_uid.toOpaqueId(), this, ConstString(), 0, nullptr, LLDB_INVALID_UID,
+      lldb_private::Type::eEncodingIsUID, decl, func_sig_ast_type,
+      lldb_private::Type::eResolveStateFull);
+}
+
 TypeSP SymbolFileNativePDB::CreateType(PdbSymUid type_uid) {
   const PdbTypeSymId &tsid = type_uid.asTypeSym();
   TypeIndex index(tsid.index);
@@ -840,6 +926,12 @@ TypeSP SymbolFileNativePDB::CreateType(P
     return CreateArrayType(type_uid, ar);
   }
 
+  if (cvt.kind() == LF_PROCEDURE) {
+    ProcedureRecord pr;
+    llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
+    return CreateProcedureType(type_uid, pr);
+  }
+
   return nullptr;
 }
 
@@ -858,7 +950,7 @@ TypeSP SymbolFileNativePDB::CreateAndCac
       auto expected_full_ti = m_index->tpi().findFullDeclForForwardRef(ti);
       if (!expected_full_ti)
         llvm::consumeError(expected_full_ti.takeError());
-      else {
+      else if (*expected_full_ti != ti) {
         full_decl_uid = PdbSymUid::makeTypeSymId(
             type_uid.tag(), *expected_full_ti, type_id.is_ipi);
 
@@ -880,6 +972,8 @@ TypeSP SymbolFileNativePDB::CreateAndCac
 
   PdbSymUid best_uid = full_decl_uid ? *full_decl_uid : type_uid;
   TypeSP result = CreateType(best_uid);
+  if (!result)
+    return nullptr;
   m_types[best_uid.toOpaqueId()] = result;
   // If we had both a forward decl and a full decl, make both point to the new
   // type.

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=345848&r1=345847&r2=345848&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h Thu Nov  1 09:37:29 2018
@@ -172,6 +172,8 @@ private:
                              const llvm::codeview::UnionRecord &ur);
   lldb::TypeSP CreateArrayType(PdbSymUid type_uid,
                                const llvm::codeview::ArrayRecord &ar);
+  lldb::TypeSP CreateProcedureType(PdbSymUid type_uid,
+                                   const llvm::codeview::ProcedureRecord &pr);
   lldb::TypeSP
   CreateClassStructUnion(PdbSymUid type_uid, llvm::StringRef name, size_t size,
                          clang::TagTypeKind ttk,




More information about the lldb-commits mailing list