zturner updated this revision to Diff 53780.
zturner added a comment.

Generated the wrong patch last time.  This one should be good


http://reviews.llvm.org/D18848

Files:
  include/lldb/Symbol/ClangASTContext.h
  source/Plugins/SymbolFile/PDB/CMakeLists.txt
  source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
  source/Plugins/SymbolFile/PDB/PDBASTParser.h
  source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
  source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
  source/Symbol/ClangASTContext.cpp
  unittests/SymbolFile/PDB/CMakeLists.txt
  unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp
  unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb
  unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp

Index: unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
===================================================================
--- unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
+++ unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
@@ -11,6 +11,8 @@
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/config.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 
@@ -20,6 +22,7 @@
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Host/FileSpec.h"
 #include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Symbol/SymbolVendor.h"
@@ -29,9 +32,12 @@
 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
 
 #if defined(_MSC_VER)
+#include "lldb/Host/windows/windows.h"
 #include <objbase.h>
 #endif
 
+#include <algorithm>
+
 extern const char *TestMainArgv0;
 
 using namespace lldb_private;
@@ -42,13 +48,17 @@
     void
     SetUp() override
     {
+// Initialize and TearDown the plugin every time, so we get a brand new
+// AST every time so that modifications to the AST from each test don't
+// leak into the next test.
 #if defined(_MSC_VER)
         ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
 #endif
 
-        HostInfoBase::Initialize();
+        HostInfo::Initialize();
         ObjectFilePECOFF::Initialize();
         SymbolFileDWARF::Initialize();
+        ClangASTContext::Initialize();
         SymbolFilePDB::Initialize();
 
         llvm::StringRef exe_folder = llvm::sys::path::parent_path(TestMainArgv0);
@@ -57,24 +67,30 @@
 
         m_pdb_test_exe = inputs_folder;
         m_dwarf_test_exe = inputs_folder;
+        m_types_test_exe = inputs_folder;
         llvm::sys::path::append(m_pdb_test_exe, "test-pdb.exe");
         llvm::sys::path::append(m_dwarf_test_exe, "test-dwarf.exe");
+        llvm::sys::path::append(m_types_test_exe, "test-pdb-types.exe");
     }
 
     void
     TearDown() override
     {
-#if defined(_MSC_VER)
-        ::CoUninitialize();
-#endif
         SymbolFilePDB::Terminate();
+        ClangASTContext::Initialize();
         SymbolFileDWARF::Terminate();
         ObjectFilePECOFF::Terminate();
+        HostInfo::Terminate();
+
+#if defined(_MSC_VER)
+        ::CoUninitialize();
+#endif
     }
 
 protected:
     llvm::SmallString<128> m_pdb_test_exe;
     llvm::SmallString<128> m_dwarf_test_exe;
+    llvm::SmallString<128> m_types_test_exe;
 
     bool
     FileSpecMatchesAsBaseOrFull(const FileSpec &left, const FileSpec &right) const
@@ -116,6 +132,35 @@
         }
         return false;
     }
+
+    int
+    GetGlobalConstantInteger(const llvm::IPDBSession &session, llvm::StringRef var) const
+    {
+        auto global = session.getGlobalScope();
+        auto results = global->findChildren(llvm::PDB_SymType::Data, var, llvm::PDB_NameSearchFlags::NS_Default);
+        uint32_t count = results->getChildCount();
+        if (count == 0)
+            return -1;
+
+        auto item = results->getChildAtIndex(0);
+        auto symbol = llvm::dyn_cast<llvm::PDBSymbolData>(item.get());
+        if (!symbol)
+            return -1;
+        llvm::Variant value = symbol->getValue();
+        switch (value.Type)
+        {
+            case llvm::PDB_VariantType::Int16:
+                return value.Value.Int16;
+            case llvm::PDB_VariantType::Int32:
+                return value.Value.Int32;
+            case llvm::PDB_VariantType::UInt16:
+                return value.Value.UInt16;
+            case llvm::PDB_VariantType::UInt32:
+                return value.Value.UInt32;
+            default:
+                return 0;
+        }
+    }
 };
 
 #if defined(HAVE_DIA_SDK)
@@ -342,3 +387,196 @@
     VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045);
     VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);
 }
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestSimpleClassTypes))
+{
+    FileSpec fspec(m_types_test_exe.c_str(), false);
+    ArchSpec aspec("i686-pc-windows");
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+    SymbolVendor *plugin = module->GetSymbolVendor();
+    SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+    const llvm::IPDBSession &session = symfile->GetPDBSession();
+    SymbolContext sc;
+    llvm::DenseSet<SymbolFile *> searched_files;
+    TypeMap results;
+    EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("Class"), nullptr, false, 0, searched_files, results));
+    EXPECT_EQ(1, results.GetSize());
+    lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
+    EXPECT_EQ(ConstString("Class"), udt_type->GetName());
+    CompilerType compiler_type = udt_type->GetForwardCompilerType();
+    EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
+    EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_Class"), udt_type->GetByteSize());
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNestedClassTypes))
+{
+    FileSpec fspec(m_types_test_exe.c_str(), false);
+    ArchSpec aspec("i686-pc-windows");
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+    SymbolVendor *plugin = module->GetSymbolVendor();
+    SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+    const llvm::IPDBSession &session = symfile->GetPDBSession();
+    SymbolContext sc;
+    llvm::DenseSet<SymbolFile *> searched_files;
+    TypeMap results;
+    EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("Class::NestedClass"), nullptr, false, 0, searched_files, results));
+    EXPECT_EQ(1, results.GetSize());
+    lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
+    EXPECT_EQ(ConstString("Class::NestedClass"), udt_type->GetName());
+    CompilerType compiler_type = udt_type->GetForwardCompilerType();
+    EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
+    EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NestedClass"), udt_type->GetByteSize());
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestClassInNamespace))
+{
+    FileSpec fspec(m_types_test_exe.c_str(), false);
+    ArchSpec aspec("i686-pc-windows");
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+    SymbolVendor *plugin = module->GetSymbolVendor();
+    SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+    const llvm::IPDBSession &session = symfile->GetPDBSession();
+    SymbolContext sc;
+    llvm::DenseSet<SymbolFile *> searched_files;
+    TypeMap results;
+    EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("NS::NSClass"), nullptr, false, 0, searched_files, results));
+    EXPECT_EQ(1, results.GetSize());
+    lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
+    EXPECT_EQ(ConstString("NS::NSClass"), udt_type->GetName());
+    CompilerType compiler_type = udt_type->GetForwardCompilerType();
+    EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
+    EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NSClass"), udt_type->GetByteSize());
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestEnumTypes))
+{
+    FileSpec fspec(m_types_test_exe.c_str(), false);
+    ArchSpec aspec("i686-pc-windows");
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+    SymbolVendor *plugin = module->GetSymbolVendor();
+    SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+    const llvm::IPDBSession &session = symfile->GetPDBSession();
+    SymbolContext sc;
+    llvm::DenseSet<SymbolFile *> searched_files;
+    const char *EnumsToCheck[] = {"Enum", "ShortEnum"};
+    for (auto Enum : EnumsToCheck)
+    {
+        TypeMap results;
+        EXPECT_EQ(1, symfile->FindTypes(sc, ConstString(Enum), nullptr, false, 0, searched_files, results));
+        EXPECT_EQ(1, results.GetSize());
+        lldb::TypeSP enum_type = results.GetTypeAtIndex(0);
+        EXPECT_EQ(ConstString(Enum), enum_type->GetName());
+        CompilerType compiler_type = enum_type->GetFullCompilerType();
+        EXPECT_TRUE(ClangASTContext::IsEnumType(compiler_type.GetOpaqueQualType()));
+        clang::EnumDecl *enum_decl = ClangASTContext::GetAsEnumDecl(compiler_type);
+        EXPECT_NE(nullptr, enum_decl);
+        EXPECT_EQ(2, std::distance(enum_decl->enumerator_begin(), enum_decl->enumerator_end()));
+
+        std::string sizeof_var = "sizeof_";
+        sizeof_var.append(Enum);
+        EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()), enum_type->GetByteSize());
+    }
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestArrayTypes))
+{
+    // In order to get this test working, we need to support lookup by symbol name.  Because array
+    // types themselves do not have names, only the symbols have names (i.e. the name of the array).
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestFunctionTypes))
+{
+    // In order to get this test working, we need to support lookup by symbol name.  Because array
+    // types themselves do not have names, only the symbols have names (i.e. the name of the array).
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestTypedefs))
+{
+    FileSpec fspec(m_types_test_exe.c_str(), false);
+    ArchSpec aspec("i686-pc-windows");
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+    SymbolVendor *plugin = module->GetSymbolVendor();
+    SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+    const llvm::IPDBSession &session = symfile->GetPDBSession();
+    SymbolContext sc;
+    llvm::DenseSet<SymbolFile *> searched_files;
+    TypeMap results;
+
+    const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef"};
+    for (auto Typedef : TypedefsToCheck)
+    {
+        TypeMap results;
+        EXPECT_EQ(1, symfile->FindTypes(sc, ConstString(Typedef), nullptr, false, 0, searched_files, results));
+        EXPECT_EQ(1, results.GetSize());
+        lldb::TypeSP typedef_type = results.GetTypeAtIndex(0);
+        EXPECT_EQ(ConstString(Typedef), typedef_type->GetName());
+        CompilerType compiler_type = typedef_type->GetFullCompilerType();
+        ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(compiler_type.GetTypeSystem());
+        EXPECT_TRUE(clang_type_system->IsTypedefType(compiler_type.GetOpaqueQualType()));
+
+        std::string sizeof_var = "sizeof_";
+        sizeof_var.append(Typedef);
+        EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()), typedef_type->GetByteSize());
+    }
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestRegexNameMatch))
+{
+    FileSpec fspec(m_types_test_exe.c_str(), false);
+    ArchSpec aspec("i686-pc-windows");
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+    SymbolVendor *plugin = module->GetSymbolVendor();
+    SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+    SymbolContext sc;
+    llvm::DenseSet<SymbolFile *> searched_files;
+    TypeMap results;
+    int num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, 0, searched_files, results);
+    EXPECT_GT(num_results, 1);
+    EXPECT_EQ(num_results, results.GetSize());
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestMaxMatches))
+{
+    FileSpec fspec(m_types_test_exe.c_str(), false);
+    ArchSpec aspec("i686-pc-windows");
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+    SymbolVendor *plugin = module->GetSymbolVendor();
+    SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+    SymbolContext sc;
+    llvm::DenseSet<SymbolFile *> searched_files;
+    TypeMap results;
+    int num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, 0, searched_files, results);
+    // Try to limit ourselves from 1 to 10 results, otherwise we could be doing this thousands of times.
+    // The idea is just to make sure that for a variety of values, the number of limited results always
+    // comes out to the number we are expecting.
+    int iterations = std::min(num_results, 10);
+    for (int i = 1; i <= iterations; ++i)
+    {
+        int num_limited_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, i, searched_files, results);
+        EXPECT_EQ(i, num_limited_results);
+        EXPECT_EQ(num_limited_results, results.GetSize());
+    }
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNullName))
+{
+    FileSpec fspec(m_types_test_exe.c_str(), false);
+    ArchSpec aspec("i686-pc-windows");
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+    SymbolVendor *plugin = module->GetSymbolVendor();
+    SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+    SymbolContext sc;
+    llvm::DenseSet<SymbolFile *> searched_files;
+    TypeMap results;
+    int num_results = symfile->FindTypes(sc, ConstString(), nullptr, false, 0, searched_files, results);
+    EXPECT_EQ(0, num_results);
+    EXPECT_EQ(0, results.GetSize());
+}
Index: unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp
===================================================================
--- /dev/null
+++ unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp
@@ -0,0 +1,86 @@
+// Compile with "cl /c /Zi /GR- /EHsc test-pdb-types.cpp"
+// Link with "link test-pdb-types.obj /debug /nodefaultlib /entry:main /out:test-pdb-types.exe"
+
+using namespace std;
+
+// Sizes of builtin types
+static const int sizeof_char = sizeof(char);
+static const int sizeof_uchar = sizeof(unsigned char);
+static const int sizeof_short = sizeof(short);
+static const int sizeof_ushort = sizeof(unsigned short);
+static const int sizeof_int = sizeof(int);
+static const int sizeof_uint = sizeof(unsigned int);
+static const int sizeof_long = sizeof(long);
+static const int sizeof_ulong = sizeof(unsigned long);
+static const int sizeof_longlong = sizeof(long long);
+static const int sizeof_ulonglong = sizeof(unsigned long long);
+static const int sizeof_int64 = sizeof(__int64);
+static const int sizeof_uint64 = sizeof(unsigned __int64);
+static const int sizeof_float = sizeof(float);
+static const int sizeof_double = sizeof(double);
+static const int sizeof_bool = sizeof(bool);
+static const int sizeof_wchar = sizeof(wchar_t);
+
+enum Enum
+{
+    EValue1 = 1,
+    EValue2 = 2,
+};
+
+enum ShortEnum : short
+{
+    ESValue1 = 1,
+    ESValue2 = 2
+};
+
+namespace NS
+{
+class NSClass
+{
+    float f;
+    double d;
+};
+}
+
+class Class
+{
+public:
+    class NestedClass
+    {
+        Enum e;
+    };
+    ShortEnum se;
+};
+
+int
+test_func(int a, int b)
+{
+    return a + b;
+}
+
+typedef Class ClassTypedef;
+typedef NS::NSClass NSClassTypedef;
+int GlobalArray[10];
+
+static const int sizeof_NSClass = sizeof(NS::NSClass);
+static const int sizeof_Class = sizeof(Class);
+static const int sizeof_NestedClass = sizeof(Class::NestedClass);
+static const int sizeof_Enum = sizeof(Enum);
+static const int sizeof_ShortEnum = sizeof(ShortEnum);
+static const int sizeof_ClassTypedef = sizeof(ClassTypedef);
+static const int sizeof_NSClassTypedef = sizeof(NSClassTypedef);
+static const int sizeof_GlobalArray = sizeof(GlobalArray);
+
+int
+main(int argc, char **argv)
+{
+    ShortEnum e1;
+    Enum e2;
+    Class c1;
+    Class::NestedClass c2;
+    NS::NSClass c3;
+
+    ClassTypedef t1;
+    NSClassTypedef t2;
+    return test_func(1, 2);
+}
Index: unittests/SymbolFile/PDB/CMakeLists.txt
===================================================================
--- unittests/SymbolFile/PDB/CMakeLists.txt
+++ unittests/SymbolFile/PDB/CMakeLists.txt
@@ -5,6 +5,8 @@
 set(test_inputs
    test-pdb.exe
    test-pdb.pdb
-   test-dwarf.exe)
+   test-dwarf.exe
+   test-pdb-types.exe
+   test-pdb-types.pdb)
 
 add_unittest_inputs(SymbolFilePDBTests "${test_inputs}")  
Index: source/Symbol/ClangASTContext.cpp
===================================================================
--- source/Symbol/ClangASTContext.cpp
+++ source/Symbol/ClangASTContext.cpp
@@ -91,6 +91,7 @@
 #include "lldb/Target/Target.h"
 
 #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
+#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
 
 #include <stdio.h>
 
@@ -3443,7 +3444,27 @@
 }
 
 bool
-ClangASTContext::IsPolymorphicClass (lldb::opaque_compiler_type_t type)
+ClangASTContext::IsClassType(lldb::opaque_compiler_type_t type)
+{
+    if (!type)
+        return false;
+    clang::QualType qual_type(GetCanonicalQualType(type));
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    return (type_class == clang::Type::Record);
+}
+
+bool
+ClangASTContext::IsEnumType(lldb::opaque_compiler_type_t type)
+{
+    if (!type)
+        return false;
+    clang::QualType qual_type(GetCanonicalQualType(type));
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    return (type_class == clang::Type::Enum);
+}
+
+bool
+ClangASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type)
 {
     if (type)
     {
@@ -5205,7 +5226,7 @@
 CompilerType
 ClangASTContext::GetBuiltinTypeByName (const ConstString &name)
 {
-    return GetBasicType (GetBasicTypeEnumeration (name));
+    return GetBasicType(GetBasicTypeEnumeration(name));
 }
 
 lldb::BasicType
@@ -9465,6 +9486,13 @@
     return m_dwarf_ast_parser_ap.get();
 }
 
+PDBASTParser *
+ClangASTContext::GetPDBParser()
+{
+    if (!m_pdb_ast_parser_ap)
+        m_pdb_ast_parser_ap.reset(new PDBASTParser(*this));
+    return m_pdb_ast_parser_ap.get();
+}
 
 bool
 ClangASTContext::LayoutRecordType(void *baton,
Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -10,11 +10,10 @@
 #ifndef lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
 #define lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
 
-#include <unordered_map>
-
 #include "lldb/Core/UserID.h"
 #include "lldb/Symbol/SymbolFile.h"
 
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/DebugInfo/PDB/IPDBSession.h"
 #include "llvm/DebugInfo/PDB/PDB.h"
 
@@ -170,6 +169,12 @@
     uint32_t
     GetPluginVersion() override;
 
+    llvm::IPDBSession &
+    GetPDBSession();
+
+    const llvm::IPDBSession &
+    GetPDBSession() const;
+
 private:
     lldb::CompUnitSP
     ParseCompileUnitForSymIndex(uint32_t id);
@@ -179,12 +184,21 @@
 
     void
     BuildSupportFileIdToSupportFileIndexMap(const llvm::PDBSymbolCompiland &cu,
-                                            std::unordered_map<uint32_t, uint32_t> &index_map) const;
+                                            llvm::DenseMap<uint32_t, uint32_t> &index_map) const;
+
+    void
+    FindTypesByRegex(const std::string &regex, uint32_t max_matches, lldb_private::TypeMap &types);
+
+    void
+    FindTypesByName(const std::string &name, uint32_t max_matches, lldb_private::TypeMap &types);
 
-    std::unordered_map<uint32_t, lldb::CompUnitSP> m_comp_units;
+    llvm::DenseMap<uint32_t, lldb::CompUnitSP> m_comp_units;
+    llvm::DenseMap<uint32_t, lldb::TypeSP> m_types;
 
+    std::vector<lldb::TypeSP> m_builtin_types;
     std::unique_ptr<llvm::IPDBSession> m_session_up;
     uint32_t m_cached_compile_unit_count;
+    std::unique_ptr<lldb_private::CompilerDeclContext> m_tu_decl_ctx_up;
 };
 
 #endif // lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -9,12 +9,16 @@
 
 #include "SymbolFilePDB.h"
 
+#include "clang/Lex/Lexer.h"
+
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/TypeMap.h"
 
 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
 #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
@@ -26,6 +30,13 @@
 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
+
+#include <regex>
 
 using namespace lldb_private;
 
@@ -116,6 +127,10 @@
 {
     lldb::addr_t obj_load_address = m_obj_file->GetFileOffset();
     m_session_up->setLoadAddress(obj_load_address);
+
+    TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+    ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+    m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>(type_system, clang_type_system->GetTranslationUnitDecl());
 }
 
 uint32_t
@@ -245,7 +260,25 @@
 lldb_private::Type *
 SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid)
 {
-    return nullptr;
+    auto find_result = m_types.find(type_uid);
+    if (find_result != m_types.end())
+        return find_result->second.get();
+
+    TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+    ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+    if (!clang_type_system)
+        return nullptr;
+    PDBASTParser *pdb = llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser());
+    if (!pdb)
+        return nullptr;
+
+    auto pdb_type = m_session_up->getSymbolById(type_uid);
+    if (pdb_type == nullptr)
+        return nullptr;
+
+    lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type);
+    m_types.insert(std::make_pair(type_uid, result));
+    return result.get();
 }
 
 bool
@@ -264,13 +297,15 @@
 lldb_private::CompilerDeclContext
 SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid)
 {
-    return lldb_private::CompilerDeclContext();
+    // PDB always uses the translation unit decl context for everything.  We can improve this later
+    // but it's not easy because PDB doesn't provide a high enough level of type fidelity in this area.
+    return *m_tu_decl_ctx_up;
 }
 
 lldb_private::CompilerDeclContext
 SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid)
 {
-    return lldb_private::CompilerDeclContext();
+    return *m_tu_decl_ctx_up;
 }
 
 void
@@ -376,14 +411,121 @@
                          llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
                          lldb_private::TypeMap &types)
 {
-    return uint32_t();
+    if (!append)
+        types.Clear();
+    if (!name)
+        return 0;
+
+    searched_symbol_files.clear();
+    searched_symbol_files.insert(this);
+
+    std::string name_str = name.AsCString();
+
+    // If this might be a regex, we have to return EVERY symbol and process them one by one, which is going
+    // to destroy performance on large PDB files.  So try really hard not to use a regex match.
+    if (name_str.find_first_of("[]?*.-+\\") != std::string::npos)
+        FindTypesByRegex(name_str, max_matches, types);
+    else
+        FindTypesByName(name_str, max_matches, types);
+    return types.GetSize();
+}
+
+void
+SymbolFilePDB::FindTypesByRegex(const std::string &regex, uint32_t max_matches, lldb_private::TypeMap &types)
+{
+    // When searching by regex, we need to go out of our way to limit the search space as much as possible, since
+    // the way this is implemented is by searching EVERYTHING in the PDB and manually doing a regex compare.  PDB
+    // library isn't optimized for regex searches or searches across multiple symbol types at the same time, so the
+    // best we can do is to search enums, then typedefs, then classes one by one, and do a regex compare against all
+    // of them.
+    llvm::PDB_SymType tags_to_search[] = {llvm::PDB_SymType::Enum, llvm::PDB_SymType::Typedef, llvm::PDB_SymType::UDT};
+    auto global = m_session_up->getGlobalScope();
+    std::unique_ptr<llvm::IPDBEnumSymbols> results;
+
+    std::regex re(regex);
+
+    uint32_t matches = 0;
+
+    for (auto tag : tags_to_search)
+    {
+        results = global->findAllChildren(tag);
+        while (auto result = results->getNext())
+        {
+            if (max_matches > 0 && matches >= max_matches)
+                break;
+
+            std::string type_name;
+            if (auto enum_type = llvm::dyn_cast<llvm::PDBSymbolTypeEnum>(result.get()))
+                type_name = enum_type->getName();
+            else if (auto typedef_type = llvm::dyn_cast<llvm::PDBSymbolTypeTypedef>(result.get()))
+                type_name = typedef_type->getName();
+            else if (auto class_type = llvm::dyn_cast<llvm::PDBSymbolTypeUDT>(result.get()))
+                type_name = class_type->getName();
+            else
+            {
+                // We're only looking for types that have names.  Skip symbols, as well as
+                // unnamed types such as arrays, pointers, etc.
+                continue;
+            }
+
+            if (!std::regex_match(type_name, re))
+                continue;
+
+            // This should cause the type to get cached and stored in the `m_types` lookup.
+            if (!ResolveTypeUID(result->getSymIndexId()))
+                continue;
+
+            auto iter = m_types.find(result->getSymIndexId());
+            if (iter == m_types.end())
+                continue;
+            types.Insert(iter->second);
+            ++matches;
+        }
+    }
+}
+
+void
+SymbolFilePDB::FindTypesByName(const std::string &name, uint32_t max_matches, lldb_private::TypeMap &types)
+{
+    auto global = m_session_up->getGlobalScope();
+    std::unique_ptr<llvm::IPDBEnumSymbols> results;
+    results = global->findChildren(llvm::PDB_SymType::None, name.c_str(), llvm::PDB_NameSearchFlags::NS_Default);
+
+    uint32_t matches = 0;
+
+    while (auto result = results->getNext())
+    {
+        if (max_matches > 0 && matches >= max_matches)
+            break;
+        switch (result->getSymTag())
+        {
+            case llvm::PDB_SymType::Enum:
+            case llvm::PDB_SymType::UDT:
+            case llvm::PDB_SymType::Typedef:
+                break;
+            default:
+                // We're only looking for types that have names.  Skip symbols, as well as
+                // unnamed types such as arrays, pointers, etc.
+                continue;
+        }
+
+        // This should cause the type to get cached and stored in the `m_types` lookup.
+        if (!ResolveTypeUID(result->getSymIndexId()))
+            continue;
+
+        auto iter = m_types.find(result->getSymIndexId());
+        if (iter == m_types.end())
+            continue;
+        types.Insert(iter->second);
+        ++matches;
+    }
 }
 
 size_t
-SymbolFilePDB::FindTypes(const std::vector<lldb_private::CompilerContext> &context, bool append,
+SymbolFilePDB::FindTypes(const std::vector<lldb_private::CompilerContext> &contexts, bool append,
                          lldb_private::TypeMap &types)
 {
-    return size_t();
+    return 0;
 }
 
 lldb_private::TypeList *
@@ -428,6 +570,18 @@
     return 1;
 }
 
+llvm::IPDBSession &
+SymbolFilePDB::GetPDBSession()
+{
+    return *m_session_up;
+}
+
+const llvm::IPDBSession &
+SymbolFilePDB::GetPDBSession() const
+{
+    return *m_session_up;
+}
+
 lldb::CompUnitSP
 SymbolFilePDB::ParseCompileUnitForSymIndex(uint32_t id)
 {
@@ -470,7 +624,7 @@
     // ParseCompileUnitSupportFiles.  But the underlying SDK gives us a globally unique
     // idenfitifier in the namespace of the PDB.  So, we have to do a mapping so that we
     // can hand out indices.
-    std::unordered_map<uint32_t, uint32_t> index_map;
+    llvm::DenseMap<uint32_t, uint32_t> index_map;
     BuildSupportFileIdToSupportFileIndexMap(*cu, index_map);
     auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
 
@@ -555,7 +709,7 @@
 
 void
 SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(const llvm::PDBSymbolCompiland &cu,
-                                                       std::unordered_map<uint32_t, uint32_t> &index_map) const
+                                                       llvm::DenseMap<uint32_t, uint32_t> &index_map) const
 {
     // This is a hack, but we need to convert the source id into an index into the support
     // files array.  We don't want to do path comparisons to avoid basename / full path
Index: source/Plugins/SymbolFile/PDB/PDBASTParser.h
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/PDB/PDBASTParser.h
@@ -0,0 +1,55 @@
+//===-- PDBASTParser.h ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SYMBOLFILE_PDB_PDBASTPARSER_H
+#define LLDB_PLUGINS_SYMBOLFILE_PDB_PDBASTPARSER_H
+
+#include "lldb/lldb-forward.h"
+
+#include "lldb/Symbol/ClangASTImporter.h"
+
+namespace clang
+{
+class CharUnits;
+class CXXRecordDecl;
+class FieldDecl;
+class RecordDecl;
+}
+
+namespace lldb_private
+{
+class ClangASTContext;
+class CompilerType;
+}
+
+namespace llvm
+{
+class PDBSymbol;
+class PDBSymbolData;
+class PDBSymbolTypeBuiltin;
+}
+
+class PDBASTParser
+{
+public:
+    PDBASTParser(lldb_private::ClangASTContext &ast);
+    ~PDBASTParser();
+
+    lldb::TypeSP
+    CreateLLDBTypeFromPDBType(const llvm::PDBSymbol &type);
+
+private:
+    bool
+    AddEnumValue(lldb_private::CompilerType enum_type, const llvm::PDBSymbolData &data) const;
+
+    lldb_private::ClangASTContext &m_ast;
+    lldb_private::ClangASTImporter m_ast_importer;
+};
+
+#endif // SymbolFileDWARF_DWARFASTParserClang_h_
Index: source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -0,0 +1,236 @@
+//===-- PDBASTParser.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PDBASTParser.h"
+
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangUtil.h"
+#include "lldb/Symbol/Declaration.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/TypeSystem.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+namespace
+{
+int
+TranslateUdtKind(PDB_UdtType pdb_kind)
+{
+    switch (pdb_kind)
+    {
+        case PDB_UdtType::Class:
+            return clang::TTK_Class;
+        case PDB_UdtType::Struct:
+            return clang::TTK_Struct;
+        case PDB_UdtType::Union:
+            return clang::TTK_Union;
+        case PDB_UdtType::Interface:
+            return clang::TTK_Interface;
+    }
+    return clang::TTK_Class;
+}
+
+lldb::Encoding
+TranslateBuiltinEncoding(PDB_BuiltinType type)
+{
+    switch (type)
+    {
+        case PDB_BuiltinType::Float:
+            return lldb::eEncodingIEEE754;
+        case PDB_BuiltinType::Int:
+        case PDB_BuiltinType::Long:
+        case PDB_BuiltinType::Char:
+            return lldb::eEncodingSint;
+        case PDB_BuiltinType::Bool:
+        case PDB_BuiltinType::UInt:
+        case PDB_BuiltinType::ULong:
+        case PDB_BuiltinType::HResult:
+            return lldb::eEncodingUint;
+        default:
+            return lldb::eEncodingInvalid;
+    }
+}
+}
+
+PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast)
+{
+}
+
+PDBASTParser::~PDBASTParser()
+{
+}
+
+// DebugInfoASTParser interface
+
+lldb::TypeSP
+PDBASTParser::CreateLLDBTypeFromPDBType(const llvm::PDBSymbol &type)
+{
+    // PDB doesn't maintain enough information to robustly rebuild the entire
+    // tree, and this is most problematic when it comes to figure out the
+    // right DeclContext to put a type in.  So for now, everything goes in
+    // the translation unit decl as a fully qualified type.
+    clang::DeclContext *tu_decl_ctx = m_ast.GetTranslationUnitDecl();
+    Declaration decl;
+
+    if (auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type))
+    {
+        AccessType access = lldb::eAccessPublic;
+        PDB_UdtType udt_kind = udt->getUdtKind();
+
+        if (udt_kind == PDB_UdtType::Class)
+            access = lldb::eAccessPrivate;
+
+        CompilerType clang_type =
+            m_ast.CreateRecordType(tu_decl_ctx, access, udt->getName().c_str(), TranslateUdtKind(udt_kind),
+                                   lldb::eLanguageTypeC_plus_plus, nullptr);
+
+        m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
+
+        return std::make_shared<Type>(type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(udt->getName()),
+                                      udt->getLength(), nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
+                                      clang_type, Type::eResolveStateForward);
+    }
+    else if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type))
+    {
+        std::string name = enum_type->getName();
+        lldb::Encoding encoding = TranslateBuiltinEncoding(enum_type->getBuiltinType());
+        uint64_t bytes = enum_type->getLength();
+        CompilerType builtin_type = m_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, bytes * 8);
+
+        CompilerType ast_enum = m_ast.CreateEnumerationType(name.c_str(), tu_decl_ctx, decl, builtin_type);
+        auto enum_values = enum_type->findAllChildren<PDBSymbolData>();
+        while (auto enum_value = enum_values->getNext())
+        {
+            if (enum_value->getDataKind() != PDB_DataKind::Constant)
+                continue;
+            AddEnumValue(ast_enum, *enum_value);
+        }
+
+        return std::make_shared<Type>(type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes, nullptr,
+                                      LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ast_enum, Type::eResolveStateFull);
+    }
+    else if (auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type))
+    {
+        Type *target_type = m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId());
+        std::string name = type_def->getName();
+        uint64_t bytes = type_def->getLength();
+        if (!target_type)
+            return nullptr;
+        CompilerType target_ast_type = target_type->GetFullCompilerType();
+        CompilerDeclContext target_decl_ctx = m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID());
+        CompilerType ast_typedef = m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx);
+        return std::make_shared<Type>(type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes,
+                                      nullptr, target_type->GetID(), Type::eEncodingIsTypedefUID, decl, ast_typedef,
+                                      Type::eResolveStateFull);
+    }
+    else if (auto func_sig = llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type))
+    {
+        auto arg_enum = func_sig->getArguments();
+        uint32_t num_args = arg_enum->getChildCount();
+        std::vector<CompilerType> arg_list(num_args);
+        while (auto arg = arg_enum->getNext())
+        {
+            Type *arg_type = m_ast.GetSymbolFile()->ResolveTypeUID(arg->getSymIndexId());
+            // If there's some error looking up one of the dependent types of this function signature, bail.
+            if (!arg_type)
+                return nullptr;
+            CompilerType arg_ast_type = arg_type->GetFullCompilerType();
+            arg_list.push_back(arg_ast_type);
+        }
+        auto pdb_return_type = func_sig->getReturnType();
+        Type *return_type = m_ast.GetSymbolFile()->ResolveTypeUID(pdb_return_type->getSymIndexId());
+        // If there's some error looking up one of the dependent types of this function signature, bail.
+        if (!return_type)
+            return nullptr;
+        CompilerType return_ast_type = return_type->GetFullCompilerType();
+        uint32_t type_quals = 0;
+        if (func_sig->isConstType())
+            type_quals |= clang::Qualifiers::Const;
+        if (func_sig->isVolatileType())
+            type_quals |= clang::Qualifiers::Volatile;
+        CompilerType func_sig_ast_type =
+            m_ast.CreateFunctionType(return_ast_type, &arg_list[0], num_args, false, type_quals);
+
+        return std::make_shared<Type>(func_sig->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), 0, nullptr,
+                                      LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_sig_ast_type,
+                                      Type::eResolveStateFull);
+    }
+    else if (auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type))
+    {
+        uint32_t num_elements = array_type->getCount();
+        uint32_t element_uid = array_type->getElementType()->getSymIndexId();
+        uint32_t bytes = array_type->getLength();
+
+        Type *element_type = m_ast.GetSymbolFile()->ResolveTypeUID(element_uid);
+        CompilerType element_ast_type = element_type->GetFullCompilerType();
+        CompilerType array_ast_type = m_ast.CreateArrayType(element_ast_type, num_elements, false);
+        return std::make_shared<Type>(array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), bytes, nullptr,
+                                      LLDB_INVALID_UID, Type::eEncodingIsUID, decl, array_ast_type,
+                                      Type::eResolveStateFull);
+    }
+    return nullptr;
+}
+
+bool
+PDBASTParser::AddEnumValue(CompilerType enum_type, const llvm::PDBSymbolData &enum_value) const
+{
+    Declaration decl;
+    Variant v = enum_value.getValue();
+    std::string name = enum_value.getName();
+    int64_t raw_value;
+    switch (v.Type)
+    {
+        case PDB_VariantType::Int8:
+            raw_value = v.Value.Int8;
+            break;
+        case PDB_VariantType::Int16:
+            raw_value = v.Value.Int16;
+            break;
+        case PDB_VariantType::Int32:
+            raw_value = v.Value.Int32;
+            break;
+        case PDB_VariantType::Int64:
+            raw_value = v.Value.Int64;
+            break;
+        case PDB_VariantType::UInt8:
+            raw_value = v.Value.UInt8;
+            break;
+        case PDB_VariantType::UInt16:
+            raw_value = v.Value.UInt16;
+            break;
+        case PDB_VariantType::UInt32:
+            raw_value = v.Value.UInt32;
+            break;
+        case PDB_VariantType::UInt64:
+            raw_value = v.Value.UInt64;
+            break;
+        default:
+            return false;
+    }
+    CompilerType underlying_type = m_ast.GetEnumerationIntegerType(enum_type.GetOpaqueQualType());
+    uint32_t byte_size = m_ast.getASTContext()->getTypeSize(ClangUtil::GetQualType(underlying_type));
+    return m_ast.AddEnumerationValueToEnumerationType(enum_type.GetOpaqueQualType(), underlying_type, decl,
+                                                      name.c_str(), raw_value, byte_size * 8);
+}
Index: source/Plugins/SymbolFile/PDB/CMakeLists.txt
===================================================================
--- source/Plugins/SymbolFile/PDB/CMakeLists.txt
+++ source/Plugins/SymbolFile/PDB/CMakeLists.txt
@@ -2,5 +2,6 @@
     DebugInfoPDB)
 
 add_lldb_library(lldbPluginSymbolFilePDB
+  PDBASTParser.cpp
   SymbolFilePDB.cpp
   )
Index: include/lldb/Symbol/ClangASTContext.h
===================================================================
--- include/lldb/Symbol/ClangASTContext.h
+++ include/lldb/Symbol/ClangASTContext.h
@@ -37,6 +37,7 @@
 #include "lldb/lldb-enumerations.h"
 
 class DWARFASTParserClang;
+class PDBASTParser;
 
 namespace lldb_private {
 
@@ -524,6 +525,8 @@
     //------------------------------------------------------------------
     DWARFASTParser *
     GetDWARFParser() override;
+    PDBASTParser *
+    GetPDBParser();
 
     //------------------------------------------------------------------
     // ClangASTContext callbacks for external source lookups.
@@ -696,7 +699,13 @@
     
     bool
     IsPolymorphicClass (lldb::opaque_compiler_type_t type) override;
-    
+
+    static bool
+    IsClassType(lldb::opaque_compiler_type_t type);
+
+    static bool
+    IsEnumType(lldb::opaque_compiler_type_t type);
+
     bool
     IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
                           CompilerType *target_type, // Can pass nullptr
@@ -1189,6 +1198,7 @@
     std::unique_ptr<clang::SelectorTable>           m_selector_table_ap;
     std::unique_ptr<clang::Builtin::Context>        m_builtins_ap;
     std::unique_ptr<DWARFASTParserClang>            m_dwarf_ast_parser_ap;
+    std::unique_ptr<PDBASTParser>                   m_pdb_ast_parser_ap;
     std::unique_ptr<ClangASTSource>                 m_scratch_ast_source_ap;
     std::unique_ptr<clang::MangleContext>           m_mangle_ctx_ap;
     CompleteTagDeclCallback                         m_callback_tag_decl;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to