Added support to the expression parser for finding

Objective-C types and enums in modules.  We now have
a three-stage fallback when looking for methods and
properties: first the DWARF, second the modules, third
the runtime.

<rdar://problem/18782288>

llvm-svn: 223939
This commit is contained in:
Sean Callanan 2014-12-10 19:23:29 +00:00
parent 80b279e624
commit dc00334dc3
1 changed files with 163 additions and 21 deletions

View File

@ -708,6 +708,8 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
else else
m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types); m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types);
bool found_a_type = false;
if (types.GetSize()) if (types.GetSize())
{ {
lldb::TypeSP type_sp = types.GetTypeAtIndex(0); lldb::TypeSP type_sp = types.GetTypeAtIndex(0);
@ -736,8 +738,62 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
} }
context.AddTypeDecl(copied_clang_type); context.AddTypeDecl(copied_clang_type);
found_a_type = true;
} }
else
if (!found_a_type)
{
// Try the modules next.
do
{
if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor())
{
bool append = false;
uint32_t max_matches = 1;
std::vector <clang::NamedDecl *> decls;
if (!modules_decl_vendor->FindDecls(name,
append,
max_matches,
decls))
break;
if (log)
{
log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in the modules",
current_id,
name.GetCString());
}
clang::NamedDecl *const decl_from_modules = decls[0];
if (llvm::isa<clang::TypeDecl>(decl_from_modules) ||
llvm::isa<clang::ObjCContainerDecl>(decl_from_modules) ||
llvm::isa<clang::EnumConstantDecl>(decl_from_modules))
{
clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr;
if (!copied_named_decl)
{
if (log)
log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the modules",
current_id);
break;
}
context.AddNamedDecl(copied_named_decl);
found_a_type = true;
}
}
} while (0);
}
if (!found_a_type)
{ {
do do
{ {
@ -896,31 +952,44 @@ FindObjCMethodDeclsWithOrigin (unsigned int current_id,
} }
DeclarationName original_decl_name(original_selector); DeclarationName original_decl_name(original_selector);
ObjCInterfaceDecl::lookup_result result = original_interface_decl->lookup(original_decl_name); llvm::SmallVector<NamedDecl *, 1> methods;
if (result.empty()) ClangASTContext::GetCompleteDecl(original_ctx, original_interface_decl);
return false;
if (ObjCMethodDecl *instance_method_decl = original_interface_decl->lookupInstanceMethod(original_selector))
if (!result[0])
return false;
for (NamedDecl *named_decl : result)
{ {
methods.push_back(instance_method_decl);
}
else if (ObjCMethodDecl *class_method_decl = original_interface_decl->lookupClassMethod(original_selector))
{
methods.push_back(class_method_decl);
}
if (methods.empty())
{
return false;
}
for (NamedDecl *named_decl : methods)
{
if (!named_decl)
continue;
ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(named_decl); ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(named_decl);
if (!result_method) if (!result_method)
return false; continue;
Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method); Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method);
if (!copied_decl) if (!copied_decl)
return false; continue;
ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
if (!copied_method_decl) if (!copied_method_decl)
return false; continue;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@ -1170,10 +1239,43 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
return; return;
} }
while (0); while (0);
do
{
// Check the modules only if the debug information didn't have a complete interface.
if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor())
{
ConstString interface_name(interface_decl->getNameAsString().c_str());
bool append = false;
uint32_t max_matches = 1;
std::vector <clang::NamedDecl *> decls;
if (!modules_decl_vendor->FindDecls(interface_name,
append,
max_matches,
decls))
break;
ObjCInterfaceDecl *interface_decl_from_modules = dyn_cast<ObjCInterfaceDecl>(decls[0]);
if (!interface_decl_from_modules)
break;
if (FindObjCMethodDeclsWithOrigin(current_id,
context,
interface_decl_from_modules,
m_ast_context,
m_ast_importer,
"in modules"))
return;
}
}
while (0);
do do
{ {
// Check the runtime only if the debug information didn't have a complete interface. // Check the runtime only if the debug information didn't have a complete interface and the modules don't get us anywhere.
lldb::ProcessSP process(m_target->GetProcessSP()); lldb::ProcessSP process(m_target->GetProcessSP());
@ -1336,10 +1438,50 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
return; return;
} }
while(0); while(0);
do
{
// Check the modules only if the debug information didn't have a complete interface.
ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor();
if (!modules_decl_vendor)
break;
bool append = false;
uint32_t max_matches = 1;
std::vector <clang::NamedDecl *> decls;
if (!modules_decl_vendor->FindDecls(class_name,
append,
max_matches,
decls))
break;
DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_modules(dyn_cast<ObjCInterfaceDecl>(decls[0]));
if (!interface_decl_from_modules.IsValid())
break;
if (log)
log->Printf("CAS::FOPD[%d] trying module (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
current_id,
static_cast<const void*>(interface_decl_from_modules.decl),
static_cast<void*>(&interface_decl_from_modules->getASTContext()));
if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
context,
*m_ast_context,
m_ast_importer,
interface_decl_from_modules))
return;
}
while(0);
do do
{ {
// Check the runtime only if the debug information didn't have a complete interface. // Check the runtime only if the debug information didn't have a complete interface
// and nothing was in the modules.
lldb::ProcessSP process(m_target->GetProcessSP()); lldb::ProcessSP process(m_target->GetProcessSP());
@ -1366,22 +1508,22 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
decls)) decls))
break; break;
DeclFromUser<const ObjCInterfaceDecl> runtime_iface_decl(dyn_cast<ObjCInterfaceDecl>(decls[0])); DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_runtime(dyn_cast<ObjCInterfaceDecl>(decls[0]));
if (!runtime_iface_decl.IsValid()) if (!interface_decl_from_runtime.IsValid())
break; break;
if (log) if (log)
log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
current_id, current_id,
static_cast<const void*>(runtime_iface_decl.decl), static_cast<const void*>(interface_decl_from_runtime.decl),
static_cast<void*>(&runtime_iface_decl->getASTContext())); static_cast<void*>(&interface_decl_from_runtime->getASTContext()));
if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
context, context,
*m_ast_context, *m_ast_context,
m_ast_importer, m_ast_importer,
runtime_iface_decl)) interface_decl_from_runtime))
return; return;
} }
while(0); while(0);