52 changes: 38 additions & 14 deletions lldb/lldb.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

30 changes: 19 additions & 11 deletions lldb/source/API/SBTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2315,14 +2315,19 @@ SBTarget::FindFirstType (const char* typename_cstr)

if (objc_language_runtime)
{
TypeVendor *objc_type_vendor = objc_language_runtime->GetTypeVendor();
DeclVendor *objc_decl_vendor = objc_language_runtime->GetDeclVendor();

if (objc_type_vendor)
if (objc_decl_vendor)
{
std::vector <ClangASTType> types;
std::vector <clang::NamedDecl *> decls;

if (objc_type_vendor->FindTypes(const_typename, true, 1, types) > 0)
return SBType(types[0]);
if (objc_decl_vendor->FindDecls(const_typename, true, 1, decls) > 0)
{
if (ClangASTType type = ClangASTContext::GetTypeForDecl(decls[0]))
{
return SBType(type);
}
}
}
}
}
Expand Down Expand Up @@ -2388,17 +2393,20 @@ SBTarget::FindTypes (const char* typename_cstr)

if (objc_language_runtime)
{
TypeVendor *objc_type_vendor = objc_language_runtime->GetTypeVendor();
DeclVendor *objc_decl_vendor = objc_language_runtime->GetDeclVendor();

if (objc_type_vendor)
if (objc_decl_vendor)
{
std::vector <ClangASTType> types;
std::vector <clang::NamedDecl *> decls;

if (objc_type_vendor->FindTypes(const_typename, true, UINT32_MAX, types))
if (objc_decl_vendor->FindDecls(const_typename, true, 1, decls) > 0)
{
for (ClangASTType &type : types)
for (clang::NamedDecl *decl : decls)
{
sb_type_list.Append(SBType(type));
if (ClangASTType type = ClangASTContext::GetTypeForDecl(decl))
{
sb_type_list.Append(SBType(type));
}
}
}
}
Expand Down
370 changes: 370 additions & 0 deletions lldb/source/Expression/ClangModulesDeclVendor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,370 @@
//===-- ClangModulesDeclVendor.cpp ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "ClangModulesDeclVendor.h"

#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Target.h"

#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/Lookup.h"
#include "clang/Serialization/ASTReader.h"

using namespace lldb_private;

namespace {
// Any Clang compiler requires a consumer for diagnostics. This one stores them as strings
// so we can provide them to the user in case a module failed to load.
class StoringDiagnosticConsumer : public clang::DiagnosticConsumer
{
public:
StoringDiagnosticConsumer ();
void
HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info);

void
ClearDiagnostics ();

void
DumpDiagnostics (Stream &error_stream);
private:
typedef std::pair<clang::DiagnosticsEngine::Level, std::string> IDAndDiagnostic;
std::vector<IDAndDiagnostic> m_diagnostics;
Log * m_log;
};

// The private implementation of our ClangModulesDeclVendor. Contains all the Clang state required
// to load modules.
class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor
{
public:
ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine,
llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation,
std::unique_ptr<clang::CompilerInstance> &&compiler_instance,
std::unique_ptr<clang::Parser> &&parser);

virtual bool
AddModule(std::vector<llvm::StringRef> &path,
Stream &error_stream);

virtual uint32_t
FindDecls (const ConstString &name,
bool append,
uint32_t max_matches,
std::vector <clang::NamedDecl*> &decls);

~ClangModulesDeclVendorImpl();

private:
clang::ModuleLoadResult
DoGetModule(clang::ModuleIdPath path, bool make_visible);

llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine;
llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> m_compiler_invocation;
std::unique_ptr<clang::CompilerInstance> m_compiler_instance;
std::unique_ptr<clang::Parser> m_parser;
};
}

StoringDiagnosticConsumer::StoringDiagnosticConsumer ()
{
m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
}

void
StoringDiagnosticConsumer::HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info)
{
llvm::SmallVector<char, 256> diagnostic_string;

info.FormatDiagnostic(diagnostic_string);

m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), diagnostic_string.size())));
}

void
StoringDiagnosticConsumer::ClearDiagnostics ()
{
m_diagnostics.clear();
}

void
StoringDiagnosticConsumer::DumpDiagnostics (Stream &error_stream)
{
for (IDAndDiagnostic &diag : m_diagnostics)
{
switch (diag.first)
{
default:
error_stream.PutCString(diag.second.c_str());
break;
case clang::DiagnosticsEngine::Level::Ignored:
break;
}
}
}

static FileSpec
GetResourceDir ()
{
static FileSpec g_cached_resource_dir;

static std::once_flag g_once_flag;

std::call_once(g_once_flag, [](){
HostInfo::GetLLDBPath (lldb::ePathTypeClangDir, g_cached_resource_dir);
});

return g_cached_resource_dir;
}


ClangModulesDeclVendor::ClangModulesDeclVendor()
{
}

ClangModulesDeclVendor::~ClangModulesDeclVendor()
{
}

ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine,
llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation,
std::unique_ptr<clang::CompilerInstance> &&compiler_instance,
std::unique_ptr<clang::Parser> &&parser) :
ClangModulesDeclVendor(),
m_diagnostics_engine(diagnostics_engine),
m_compiler_invocation(compiler_invocation),
m_compiler_instance(std::move(compiler_instance)),
m_parser(std::move(parser))
{
}

bool
ClangModulesDeclVendorImpl::AddModule(std::vector<llvm::StringRef> &path,
Stream &error_stream)
{
// Fail early.

if (m_compiler_instance->hadModuleLoaderFatalFailure())
{
error_stream.PutCString("error: Couldn't load a module because the module loader is in a fatal state.\n");
return false;
}

if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0]))
{
error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].str().c_str());
return false;
}

llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>, 4> clang_path;

{
size_t source_loc_counter = 0;
clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager();

for (llvm::StringRef &component : path)
{
clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(component),
source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(source_loc_counter++)));
}
}

StoringDiagnosticConsumer *diagnostic_consumer = static_cast<StoringDiagnosticConsumer *>(m_compiler_instance->getDiagnostics().getClient());

diagnostic_consumer->ClearDiagnostics();

clang::Module *top_level_module = DoGetModule(clang_path.front(), false);

if (!top_level_module)
{
diagnostic_consumer->DumpDiagnostics(error_stream);
error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].str().c_str());
return false;
}

clang::Module *submodule = top_level_module;

for (size_t ci = 1; ci < path.size(); ++ci)
{
llvm::StringRef &component = path[ci];
submodule = submodule->findSubmodule(component.str());
if (!submodule)
{
diagnostic_consumer->DumpDiagnostics(error_stream);
error_stream.Printf("error: Couldn't load submodule %s\n", component.str().c_str());
return false;
}
}

clang::Module *requested_module = DoGetModule(clang_path, true);

return (requested_module != nullptr);
}

// ClangImporter::lookupValue

uint32_t
ClangModulesDeclVendorImpl::FindDecls (const ConstString &name,
bool append,
uint32_t max_matches,
std::vector <clang::NamedDecl*> &decls)
{
if (!append)
decls.clear();

clang::IdentifierInfo &ident = m_compiler_instance->getASTContext().Idents.get(name.GetStringRef());

clang::LookupResult lookup_result(m_compiler_instance->getSema(),
clang::DeclarationName(&ident),
clang::SourceLocation(),
clang::Sema::LookupOrdinaryName);

m_compiler_instance->getSema().LookupName(lookup_result, m_compiler_instance->getSema().getScopeForContext(m_compiler_instance->getASTContext().getTranslationUnitDecl()));

uint32_t num_matches = 0;

for (clang::NamedDecl *named_decl : lookup_result)
{
if (num_matches >= max_matches)
return num_matches;

decls.push_back(named_decl);
++num_matches;
}

return num_matches;
}

ClangModulesDeclVendorImpl::~ClangModulesDeclVendorImpl()
{
}

clang::ModuleLoadResult
ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
bool make_visible)
{
clang::Module::NameVisibilityKind visibility = make_visible ? clang::Module::AllVisible : clang::Module::Hidden;

const bool is_inclusion_directive = false;

return m_compiler_instance->loadModule(path.front().second, path, visibility, is_inclusion_directive);
}

static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";

lldb_private::ClangModulesDeclVendor *
ClangModulesDeclVendor::Create(Target &target)
{
// FIXME we should insure programmatically that the expression parser's compiler and the modules runtime's
// compiler are both initialized in the same way – preferably by the same code.

if (!target.GetPlatform()->SupportsModules())
return nullptr;

const ArchSpec &arch = target.GetArchitecture();

std::vector<std::string> compiler_invocation_arguments =
{
"-fmodules",
"-fcxx-modules",
"-fsyntax-only",
"-femit-all-decls",
"-target", arch.GetTriple().str(),
"-fmodules-validate-system-headers",
"-Werror=non-modular-include-in-framework-module"
};

target.GetPlatform()->AddClangModuleCompilationOptions(compiler_invocation_arguments);

compiler_invocation_arguments.push_back(ModuleImportBufferName);

// Add additional search paths with { "-I", path } or { "-F", path } here.

{
llvm::SmallString<128> DefaultModuleCache;
const bool erased_on_reboot = false;
llvm::sys::path::system_temp_directory(erased_on_reboot, DefaultModuleCache);
llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang");
llvm::sys::path::append(DefaultModuleCache, "ModuleCache");
std::string module_cache_argument("-fmodules-cache-path=");
module_cache_argument.append(DefaultModuleCache.str().str());
compiler_invocation_arguments.push_back(module_cache_argument);
}

{
FileSpec clang_resource_dir = GetResourceDir();

if (clang_resource_dir.IsDirectory())
{
compiler_invocation_arguments.push_back("-resource-dir");
compiler_invocation_arguments.push_back(clang_resource_dir.GetPath());
}
}

llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions,
new StoringDiagnosticConsumer);

std::vector<const char *> compiler_invocation_argument_cstrs;

for (const std::string &arg : compiler_invocation_arguments) {
compiler_invocation_argument_cstrs.push_back(arg.c_str());
}

llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> invocation(clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, diagnostics_engine));

if (!invocation)
return nullptr;

std::unique_ptr<llvm::MemoryBuffer> source_buffer = llvm::MemoryBuffer::getMemBuffer("extern int __lldb __attribute__((unavailable));",
ModuleImportBufferName);

invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, source_buffer.release());

std::unique_ptr<clang::CompilerInstance> instance(new clang::CompilerInstance);

instance->setDiagnostics(diagnostics_engine.get());
instance->setInvocation(invocation.get());

std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);

instance->setTarget(clang::TargetInfo::CreateTargetInfo(*diagnostics_engine, instance->getInvocation().TargetOpts));

if (!instance->hasTarget())
return nullptr;

instance->getTarget().adjust(instance->getLangOpts());

if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0]))
return nullptr;

instance->getPreprocessor().enableIncrementalProcessing();

instance->createModuleManager();

instance->createSema(action->getTranslationUnitKind(), nullptr);

const bool skipFunctionBodies = false;
std::unique_ptr<clang::Parser> parser(new clang::Parser(instance->getPreprocessor(), instance->getSema(), skipFunctionBodies));

instance->getPreprocessor().EnterMainSourceFile();
parser->Initialize();

clang::Parser::DeclGroupPtrTy parsed;

while (!parser->ParseTopLevelDecl(parsed));

return new ClangModulesDeclVendorImpl (diagnostics_engine, invocation, std::move(instance), std::move(parser));
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===-- AppleObjCSymbolVendor.cpp -------------------------------*- C++ -*-===//
//===-- AppleObjCDeclVendor.cpp ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
Expand All @@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//

#include "AppleObjCTypeVendor.h"
#include "AppleObjCDeclVendor.h"

#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
Expand All @@ -25,8 +25,8 @@ using namespace lldb_private;
class lldb_private::AppleObjCExternalASTSource : public ClangExternalASTSourceCommon
{
public:
AppleObjCExternalASTSource (AppleObjCTypeVendor &type_vendor) :
m_type_vendor(type_vendor)
AppleObjCExternalASTSource (AppleObjCDeclVendor &decl_vendor) :
m_decl_vendor(decl_vendor)
{
}

Expand Down Expand Up @@ -57,7 +57,7 @@ class lldb_private::AppleObjCExternalASTSource : public ClangExternalASTSourceCo

clang::ObjCInterfaceDecl *non_const_interface_decl = const_cast<clang::ObjCInterfaceDecl*>(interface_decl);

if (!m_type_vendor.FinishDecl(non_const_interface_decl))
if (!m_decl_vendor.FinishDecl(non_const_interface_decl))
break;

clang::DeclContext::lookup_const_result result = non_const_interface_decl->lookup(name);
Expand Down Expand Up @@ -129,7 +129,7 @@ class lldb_private::AppleObjCExternalASTSource : public ClangExternalASTSourceCo
dumper.ToLog(log, " [CT] ");
}

m_type_vendor.FinishDecl(interface_decl);
m_decl_vendor.FinishDecl(interface_decl);

if (log)
{
Expand All @@ -153,16 +153,16 @@ class lldb_private::AppleObjCExternalASTSource : public ClangExternalASTSourceCo

void StartTranslationUnit (clang::ASTConsumer *Consumer)
{
clang::TranslationUnitDecl *translation_unit_decl = m_type_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl();
clang::TranslationUnitDecl *translation_unit_decl = m_decl_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl();
translation_unit_decl->setHasExternalVisibleStorage();
translation_unit_decl->setHasExternalLexicalStorage();
}
private:
AppleObjCTypeVendor &m_type_vendor;
AppleObjCDeclVendor &m_decl_vendor;
};

AppleObjCTypeVendor::AppleObjCTypeVendor(ObjCLanguageRuntime &runtime) :
TypeVendor(),
AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime) :
DeclVendor(),
m_runtime(runtime),
m_ast_ctx(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().getTriple().c_str()),
m_type_realizer_sp(m_runtime.GetEncodingToType())
Expand All @@ -173,7 +173,7 @@ AppleObjCTypeVendor::AppleObjCTypeVendor(ObjCLanguageRuntime &runtime) :
}

clang::ObjCInterfaceDecl*
AppleObjCTypeVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa)
AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa)
{
ISAToInterfaceMap::const_iterator iter = m_isa_to_interface.find(isa);

Expand Down Expand Up @@ -421,7 +421,7 @@ class ObjCRuntimeMethodType
};

bool
AppleObjCTypeVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl)
AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl)
{
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?

Expand Down Expand Up @@ -534,7 +534,7 @@ AppleObjCTypeVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl)
{
ASTDumper method_dumper ((clang::Decl*)interface_decl);

log->Printf("[AppleObjCTypeVendor::FinishDecl] Finishing Objective-C interface for %s", descriptor->GetClassName().AsCString());
log->Printf("[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C interface for %s", descriptor->GetClassName().AsCString());
}


Expand All @@ -548,7 +548,7 @@ AppleObjCTypeVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl)
{
ASTDumper method_dumper ((clang::Decl*)interface_decl);

log->Printf("[AppleObjCTypeVendor::FinishDecl] Finished Objective-C interface");
log->Printf("[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface");

method_dumper.ToLog(log, " [AOTV::FD] ");
}
Expand All @@ -557,25 +557,25 @@ AppleObjCTypeVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl)
}

uint32_t
AppleObjCTypeVendor::FindTypes (const ConstString &name,
AppleObjCDeclVendor::FindDecls (const ConstString &name,
bool append,
uint32_t max_matches,
std::vector <ClangASTType> &types)
std::vector <clang::NamedDecl *> &decls)
{
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;

Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?

if (log)
log->Printf("AppleObjCTypeVendor::FindTypes [%u] ('%s', %s, %u, )",
log->Printf("AppleObjCDeclVendor::FindTypes [%u] ('%s', %s, %u, )",
current_id,
(const char*)name.AsCString(),
append ? "true" : "false",
max_matches);

if (!append)
types.clear();
decls.clear();

uint32_t ret = 0;

Expand All @@ -592,12 +592,11 @@ AppleObjCTypeVendor::FindTypes (const ConstString &name,

if (!lookup_result.empty())
{
if (const clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0]))
if (clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0]))
{
clang::QualType result_iface_type = ast_ctx->getObjCInterfaceType(result_iface_decl);

if (log)
{
clang::QualType result_iface_type = ast_ctx->getObjCInterfaceType(result_iface_decl);
ASTDumper dumper(result_iface_type);

uint64_t isa_value = LLDB_INVALID_ADDRESS;
Expand All @@ -611,7 +610,7 @@ AppleObjCTypeVendor::FindTypes (const ConstString &name,
isa_value);
}

types.push_back(ClangASTType(ast_ctx, result_iface_type.getAsOpaquePtr()));
decls.push_back(result_iface_decl);
ret++;
break;
}
Expand Down Expand Up @@ -655,18 +654,17 @@ AppleObjCTypeVendor::FindTypes (const ConstString &name,
break;
}

clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(iface_decl);

if (log)
{
clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(iface_decl);
ASTDumper dumper(new_iface_type);
log->Printf("AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")",
current_id,
dumper.GetCString(),
(uint64_t)isa);
}

types.push_back(ClangASTType(ast_ctx, new_iface_type.getAsOpaquePtr()));
decls.push_back(iface_decl);
ret++;
break;
} while (0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===-- AppleObjCSymbolVendor.h ---------------------------------*- C++ -*-===//
//===-- AppleObjCDeclVendor.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
Expand All @@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_AppleObjCSymbolVendor_h_
#define liblldb_AppleObjCSymbolVendor_h_
#ifndef liblldb_AppleObjCDeclVendor_h_
#define liblldb_AppleObjCDeclVendor_h_

// C Includes
// C++ Includes
Expand All @@ -20,30 +20,24 @@
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/TypeVendor.h"
#include "lldb/Symbol/DeclVendor.h"
#include "lldb/Target/ObjCLanguageRuntime.h"

namespace lldb_private {

class AppleObjCExternalASTSource;

class AppleObjCTypeVendor : public TypeVendor
class AppleObjCDeclVendor : public DeclVendor
{
public:
AppleObjCTypeVendor(ObjCLanguageRuntime &runtime);
AppleObjCDeclVendor(ObjCLanguageRuntime &runtime);

virtual uint32_t
FindTypes (const ConstString &name,
FindDecls (const ConstString &name,
bool append,
uint32_t max_matches,
std::vector <ClangASTType> &types);

virtual clang::ASTContext *
GetClangASTContext ()
{
return m_ast_ctx.getASTContext();
}

std::vector <clang::NamedDecl *> &decls);

friend class AppleObjCExternalASTSource;
private:
clang::ObjCInterfaceDecl *GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa);
Expand All @@ -61,4 +55,4 @@ class AppleObjCTypeVendor : public TypeVendor

} // namespace lldb_private

#endif // liblldb_AppleObjCSymbolVendor_h_
#endif // liblldb_AppleObjCDeclVendor_h_
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#include "AppleObjCRuntimeV1.h"
#include "AppleObjCTrampolineHandler.h"
#include "AppleObjCTypeVendor.h"
#include "AppleObjCDeclVendor.h"

#include "clang/AST/Type.h"

Expand Down Expand Up @@ -445,11 +445,11 @@ AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded()
}
}

TypeVendor *
AppleObjCRuntimeV1::GetTypeVendor()
DeclVendor *
AppleObjCRuntimeV1::GetDeclVendor()
{
if (!m_type_vendor_ap.get())
m_type_vendor_ap.reset(new AppleObjCTypeVendor(*this));
if (!m_decl_vendor_ap.get())
m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this));

return m_type_vendor_ap.get();
return m_decl_vendor_ap.get();
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ class AppleObjCRuntimeV1 :
virtual void
UpdateISAToDescriptorMapIfNeeded();

virtual TypeVendor *
GetTypeVendor();
virtual DeclVendor *
GetDeclVendor();

protected:
virtual lldb::BreakpointResolverSP
Expand Down Expand Up @@ -188,7 +188,7 @@ class AppleObjCRuntimeV1 :

HashTableSignature m_hash_signature;
lldb::addr_t m_isa_hash_table_ptr;
std::unique_ptr<TypeVendor> m_type_vendor_ap;
std::unique_ptr<DeclVendor> m_decl_vendor_ap;
private:
AppleObjCRuntimeV1(Process *process);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@
#include "AppleObjCRuntimeV2.h"
#include "AppleObjCClassDescriptorV2.h"
#include "AppleObjCTypeEncodingParser.h"
#include "AppleObjCTypeVendor.h"
#include "AppleObjCDeclVendor.h"
#include "AppleObjCTrampolineHandler.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"

#include <vector>

Expand Down Expand Up @@ -346,7 +347,7 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process,
m_get_shared_cache_class_info_code(),
m_get_shared_cache_class_info_args (LLDB_INVALID_ADDRESS),
m_get_shared_cache_class_info_args_mutex (Mutex::eMutexTypeNormal),
m_type_vendor_ap (),
m_decl_vendor_ap (),
m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS),
m_hash_signature (),
m_has_object_getClass (false),
Expand Down Expand Up @@ -401,12 +402,12 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
else
{
// try to go for a ClangASTType at least
TypeVendor* vendor = GetTypeVendor();
DeclVendor* vendor = GetDeclVendor();
if (vendor)
{
std::vector<ClangASTType> types;
if (vendor->FindTypes(class_name, false, 1, types) && types.size() && types.at(0).IsValid())
class_type_or_name.SetClangASTType(types.at(0));
std::vector<clang::NamedDecl*> decls;
if (vendor->FindDecls(class_name, false, 1, decls) && decls.size())
class_type_or_name.SetClangASTType(ClangASTContext::GetTypeForDecl(decls[0]));
}
}
}
Expand Down Expand Up @@ -1576,13 +1577,13 @@ AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
return ObjCLanguageRuntime::GetActualTypeName(isa);
}

TypeVendor *
AppleObjCRuntimeV2::GetTypeVendor()
DeclVendor *
AppleObjCRuntimeV2::GetDeclVendor()
{
if (!m_type_vendor_ap.get())
m_type_vendor_ap.reset(new AppleObjCTypeVendor(*this));
if (!m_decl_vendor_ap.get())
m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this));

return m_type_vendor_ap.get();
return m_decl_vendor_ap.get();
}

lldb::addr_t
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ class AppleObjCRuntimeV2 :
virtual ClassDescriptorSP
GetClassDescriptorFromISA (ObjCISA isa);

virtual TypeVendor *
GetTypeVendor();
virtual DeclVendor *
GetDeclVendor();

virtual lldb::addr_t
LookupRuntimeSymbol (const ConstString &name);
Expand Down Expand Up @@ -280,7 +280,7 @@ class AppleObjCRuntimeV2 :
lldb::addr_t m_get_shared_cache_class_info_args;
Mutex m_get_shared_cache_class_info_args_mutex;

std::unique_ptr<TypeVendor> m_type_vendor_ap;
std::unique_ptr<DeclVendor> m_decl_vendor_ap;
lldb::addr_t m_isa_hash_table_ptr;
HashTableSignature m_hash_signature;
bool m_has_object_getClass;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,23 +240,22 @@ AppleObjCTypeEncodingParser::BuildObjCObjectPointerType (clang::ASTContext &ast_
name.erase(less_than_pos);
}

TypeVendor *type_vendor = m_runtime.GetTypeVendor();
DeclVendor *decl_vendor = m_runtime.GetDeclVendor();

assert (type_vendor); // how are we parsing type encodings for expressions if a type vendor isn't in play?
assert (type_vendor->GetClangASTContext() == &ast_ctx); // it doesn't make sense for us to be looking in other places
assert (decl_vendor); // how are we parsing type encodings for expressions if a type vendor isn't in play?

const bool append = false;
const uint32_t max_matches = 1;
std::vector<ClangASTType> types;
std::vector<clang::NamedDecl *> decls;

uint32_t num_types = type_vendor->FindTypes(ConstString(name),
uint32_t num_types = decl_vendor->FindDecls(ConstString(name),
append,
max_matches,
types);
decls);

assert(num_types); // how can a type be mentioned in runtime type signatures and not be in the runtime?

return types[0].GetPointerType().GetQualType();
return ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType().GetQualType();
}
else
{
Expand Down
14 changes: 12 additions & 2 deletions lldb/source/Symbol/ClangASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1132,14 +1132,24 @@ ClangASTContext::AreTypesSame (ClangASTType type1,
return ast->hasSameType (type1_qual, type2_qual);
}

ClangASTType
ClangASTContext::GetTypeForDecl (clang::NamedDecl *decl)
{
if (clang::ObjCInterfaceDecl *interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl))
return GetTypeForDecl(interface_decl);
if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl))
return GetTypeForDecl(tag_decl);
return ClangASTType();
}


ClangASTType
ClangASTContext::GetTypeForDecl (TagDecl *decl)
{
// No need to call the getASTContext() accessor (which can create the AST
// if it isn't created yet, because we can't have created a decl in this
// AST if our AST didn't already exist...
ASTContext *ast = m_ast_ap.get();
ASTContext *ast = &decl->getASTContext();
if (ast)
return ClangASTType (ast, ast->getTagDeclType(decl).getAsOpaquePtr());
return ClangASTType();
Expand All @@ -1151,7 +1161,7 @@ ClangASTContext::GetTypeForDecl (ObjCInterfaceDecl *decl)
// No need to call the getASTContext() accessor (which can create the AST
// if it isn't created yet, because we can't have created a decl in this
// AST if our AST didn't already exist...
ASTContext *ast = m_ast_ap.get();
ASTContext *ast = &decl->getASTContext();
if (ast)
return ClangASTType (ast, ast->getObjCInterfaceType(decl).getAsOpaquePtr());
return ClangASTType();
Expand Down
16 changes: 16 additions & 0 deletions lldb/source/Target/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2028,6 +2028,22 @@ Target::GetSourceManager ()
return *m_source_manager_ap;
}

ClangModulesDeclVendor *
Target::GetClangModulesDeclVendor ()
{
static Mutex s_clang_modules_decl_vendor_mutex; // If this is contended we can make it per-target

{
Mutex::Locker clang_modules_decl_vendor_locker(s_clang_modules_decl_vendor_mutex);

if (!m_clang_modules_decl_vendor_ap)
{
m_clang_modules_decl_vendor_ap.reset(ClangModulesDeclVendor::Create(*this));
}
}

return m_clang_modules_decl_vendor_ap.get();
}

Target::StopHookSP
Target::CreateStopHook ()
Expand Down