[Lldb-commits] [lldb] r266392 - Initial support for reading type information from PDBs.

Zachary Turner via lldb-commits lldb-commits at lists.llvm.org
Thu Apr 14 17:21:27 PDT 2016


Author: zturner
Date: Thu Apr 14 19:21:26 2016
New Revision: 266392

URL: http://llvm.org/viewvc/llvm-project?rev=266392&view=rev
Log:
Initial support for reading type information from PDBs.

This implements a PDBASTParser and corresponding logic in
SymbolFilePDB to do type lookup by name.  This is just a first
pass and leaves many aspects of type lookup unimplemented, and
just focuses on laying the framework.  With this patch, you should
be able to lookup basic types by name from a PDB.

Full class definitions are not completed yet, we will instead
just return a forward declaration of the class.

Differential Revision: http://reviews.llvm.org/D18848
Reviewed by: Greg Clayton

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

Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=266392&r1=266391&r2=266392&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Thu Apr 14 19:21:26 2016
@@ -37,6 +37,7 @@
 #include "lldb/lldb-enumerations.h"
 
 class DWARFASTParserClang;
+class PDBASTParser;
 
 namespace lldb_private {
 
@@ -524,6 +525,8 @@ public:
     //------------------------------------------------------------------
     DWARFASTParser *
     GetDWARFParser() override;
+    PDBASTParser *
+    GetPDBParser();
 
     //------------------------------------------------------------------
     // ClangASTContext callbacks for external source lookups.
@@ -696,7 +699,13 @@ public:
     
     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 @@ protected:
     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;

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt?rev=266392&r1=266391&r2=266392&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt Thu Apr 14 19:21:26 2016
@@ -2,5 +2,6 @@ set(LLVM_PRIVATE_LINK_COMPONENTS
     DebugInfoPDB)
 
 add_lldb_library(lldbPluginSymbolFilePDB
+  PDBASTParser.cpp
   SymbolFilePDB.cpp
   )

Added: lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp?rev=266392&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp (added)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp Thu Apr 14 19:21:26 2016
@@ -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);
+}

Added: lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h?rev=266392&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h (added)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/PDBASTParser.h Thu Apr 14 19:21:26 2016
@@ -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_

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp?rev=266392&r1=266391&r2=266392&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp Thu Apr 14 19:21:26 2016
@@ -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 @@ SymbolFilePDB::InitializeObject()
 {
     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 @@ SymbolFilePDB::ParseVariablesForContext(
 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 @@ SymbolFilePDB::GetDeclForUID(lldb::user_
 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 @@ SymbolFilePDB::FindTypes(const lldb_priv
                          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 @@ SymbolFilePDB::GetPluginVersion()
     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 @@ SymbolFilePDB::ParseCompileUnitLineTable
     // 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 @@ SymbolFilePDB::ParseCompileUnitLineTable
 
 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

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h?rev=266392&r1=266391&r2=266392&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h Thu Apr 14 19:21:26 2016
@@ -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 @@ public:
     uint32_t
     GetPluginVersion() override;
 
+    llvm::IPDBSession &
+    GetPDBSession();
+
+    const llvm::IPDBSession &
+    GetPDBSession() const;
+
 private:
     lldb::CompUnitSP
     ParseCompileUnitForSymIndex(uint32_t id);
@@ -179,12 +184,21 @@ private:
 
     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_

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=266392&r1=266391&r2=266392&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Thu Apr 14 19:21:26 2016
@@ -90,6 +90,7 @@
 #include "lldb/Target/Target.h"
 
 #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
+#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
 
 #include <stdio.h>
 
@@ -3442,7 +3443,27 @@ ClangASTContext::IsObjCObjectOrInterface
 }
 
 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)
     {
@@ -5204,7 +5225,7 @@ ClangASTContext::GetNumChildren (lldb::o
 CompilerType
 ClangASTContext::GetBuiltinTypeByName (const ConstString &name)
 {
-    return GetBasicType (GetBasicTypeEnumeration (name));
+    return GetBasicType(GetBasicTypeEnumeration(name));
 }
 
 lldb::BasicType
@@ -9472,6 +9493,13 @@ ClangASTContext::GetDWARFParser()
     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,

Modified: lldb/trunk/unittests/SymbolFile/PDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/CMakeLists.txt?rev=266392&r1=266391&r2=266392&view=diff
==============================================================================
--- lldb/trunk/unittests/SymbolFile/PDB/CMakeLists.txt (original)
+++ lldb/trunk/unittests/SymbolFile/PDB/CMakeLists.txt Thu Apr 14 19:21:26 2016
@@ -5,6 +5,8 @@ add_lldb_unittest(SymbolFilePDBTests
 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}")  

Added: lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp?rev=266392&view=auto
==============================================================================
--- lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp (added)
+++ lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp Thu Apr 14 19:21:26 2016
@@ -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);
+}

Added: lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb?rev=266392&view=auto
==============================================================================
Binary files lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb (added) and lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb Thu Apr 14 19:21:26 2016 differ

Modified: lldb/trunk/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp?rev=266392&r1=266391&r2=266392&view=diff
==============================================================================
--- lldb/trunk/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp (original)
+++ lldb/trunk/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp Thu Apr 14 19:21:26 2016
@@ -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 @@ public:
     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 @@ public:
 
         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 @@ protected:
         }
         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 @@ TEST_F(SymbolFilePDBTests, REQUIRES_DIA_
     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());
+}




More information about the lldb-commits mailing list