As part of the work to make Objective-C type information

from symbols more accessible, I have added a second
map to the ClangASTImporter: the ObjCInterfaceMetaMap.
This map keeps track of all type definitions found for
a particular Objective-C interface, allowing the
ClangASTSource to refer to all possible sources when
looking for method definitions.

There is a bug in lookup that I still need to figure out,
but after that we should be able to report full method
information for Objective-C classes shown in symbols.

Also fixed some errors I ran into when enabling the maps
for the persistent type store.  The persistent type store
previously did not use the ClangASTImporter to import
types, instead using ASTImporters that got allocated each
time a type needed copying.  To support the requirements
of the persistent type store -- namely, that types must be
copied, completed, and then completely severed from their
origin in the parser's AST context (which will go away) --
I added a new function called DeportType which severs all
these connections.

llvm-svn: 145914
This commit is contained in:
Sean Callanan
2011-12-06 03:41:14 +00:00
parent 32772f7790
commit 0eed0d42a0
8 changed files with 268 additions and 69 deletions

View File

@@ -45,14 +45,13 @@ public:
/// The type that the result should have. May be initialized with a
/// NULL type, in which case the type is inferred.
///
/// @param[in] scratch_ast_context
/// If non-NULL, an AST context to populate with the persistent types
/// found in the expression.
/// @param[in] target
/// The target, which contains the persistent variable store and the
/// AST importer.
//----------------------------------------------------------------------
ASTResultSynthesizer(clang::ASTConsumer *passthrough,
TypeFromUser desired_type,
clang::ASTContext &scratch_ast_context,
ClangPersistentVariables &persistent_vars);
Target &target);
//----------------------------------------------------------------------
/// Destructor
@@ -181,8 +180,7 @@ private:
clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types.
clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer.
clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer.
clang::ASTContext &m_scratch_ast_context; ///< The AST context to install persistent types into.
ClangPersistentVariables &m_persistent_vars;///< The persistent variable manager to register persistent types with.
Target &m_target; ///< The target, which contains the persistent variable store and the
clang::Sema *m_sema; ///< The Sema to use.
TypeFromUser m_desired_type; ///< If non-NULL, the type to coerce the result to.
};

View File

@@ -32,13 +32,13 @@ namespace lldb_private {
//----------------------------------------------------------------------
class ClangASTSource :
public ClangExternalASTSourceCommon,
public ClangASTImporter::NamespaceMapCompleter
public ClangASTImporter::MapCompleter
{
public:
//------------------------------------------------------------------
/// Constructor
///
/// Initializes class variabes.
/// Initializes class variables.
///
/// @param[in] declMap
/// A reference to the LLDB object that handles entity lookup.
@@ -73,6 +73,7 @@ public:
void InstallASTContext (clang::ASTContext *ast_context)
{
m_ast_context = ast_context;
m_ast_importer->InstallMapCompleter(ast_context, *this);
}
//
@@ -169,6 +170,24 @@ public:
const ConstString &name,
ClangASTImporter::NamespaceMapSP &parent_map) const;
//------------------------------------------------------------------
/// Look up all instances of a given Objective-C interface in all
/// symbol files and put the appropriate entries in the namespace
/// map.
///
/// @param[in] namespace_map
/// The map to be completed.
///
/// @param[in] name
/// The name of the namespace to be found.
///
/// @param[in] parent_map
/// The map for the namespace's parent namespace, if there is
/// one.
//------------------------------------------------------------------
void CompleteObjCInterfaceMap (ClangASTImporter::ObjCInterfaceMapSP &objc_interface_map,
const ConstString &name) const;
//
// Helper APIs
//

View File

@@ -47,6 +47,11 @@ public:
CopyDecl (clang::ASTContext *dst_ctx,
clang::ASTContext *src_ctx,
clang::Decl *decl);
clang::Decl *
DeportDecl (clang::ASTContext *dst_ctx,
clang::ASTContext *src_ctx,
clang::Decl *decl);
void
CompleteTagDecl (clang::TagDecl *decl);
@@ -68,23 +73,49 @@ public:
return origin.Valid();
}
//
// Namespace maps
//
typedef std::vector < std::pair<lldb::ModuleSP, ClangNamespaceDecl> > NamespaceMap;
typedef lldb::SharedPtr<NamespaceMap>::Type NamespaceMapSP;
void RegisterNamespaceMap (const clang::NamespaceDecl *decl,
NamespaceMapSP &namespace_map);
NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl);
class NamespaceMapCompleter
void BuildNamespaceMap (const clang::NamespaceDecl *decl);
//
// Objective-C interface maps
//
typedef std::vector <ClangASTType> ObjCInterfaceMap;
typedef lldb::SharedPtr<ObjCInterfaceMap>::Type ObjCInterfaceMapSP;
void BuildObjCInterfaceMap (const clang::ObjCInterfaceDecl *decl);
ObjCInterfaceMapSP GetObjCInterfaceMap (const clang::ObjCInterfaceDecl *decl);
//
// Completers for the namespace and Objective-C interface maps
//
class MapCompleter
{
public:
virtual ~NamespaceMapCompleter ();
virtual ~MapCompleter ();
virtual void CompleteNamespaceMap (NamespaceMapSP &namespace_map,
const ConstString &name,
NamespaceMapSP &parent_map) const = 0;
virtual void CompleteObjCInterfaceMap (ObjCInterfaceMapSP &objc_interface_map,
const ConstString &name) const = 0;
};
void InstallMapCompleter (clang::ASTContext *dst_ctx, NamespaceMapCompleter &completer)
void InstallMapCompleter (clang::ASTContext *dst_ctx, MapCompleter &completer)
{
ASTContextMetadataSP context_md;
ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
@@ -98,13 +129,9 @@ public:
{
context_md = context_md_iter->second;
}
context_md->m_map_completer = &completer;
}
NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl);
void BuildNamespaceMap (const clang::NamespaceDecl *decl);
void ForgetDestination (clang::ASTContext *dst_ctx);
void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
@@ -170,11 +197,10 @@ private:
clang::ASTContext *m_source_ctx;
};
typedef lldb::SharedPtr<Minion>::Type MinionSP;
typedef std::map<clang::ASTContext *, MinionSP> MinionMap;
typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP> NamespaceMetaMap;
typedef lldb::SharedPtr<Minion>::Type MinionSP;
typedef std::map<clang::ASTContext *, MinionSP> MinionMap;
typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP> NamespaceMetaMap;
typedef std::map<const clang::ObjCInterfaceDecl *, ObjCInterfaceMapSP> ObjCInterfaceMetaMap;
struct ASTContextMetadata
{
@@ -183,16 +209,19 @@ private:
m_minions (),
m_origins (),
m_namespace_maps (),
m_objc_interface_maps (),
m_map_completer (NULL)
{
}
clang::ASTContext *m_dst_ctx;
MinionMap m_minions;
OriginMap m_origins;
clang::ASTContext *m_dst_ctx;
MinionMap m_minions;
OriginMap m_origins;
NamespaceMetaMap m_namespace_maps;
NamespaceMapCompleter *m_map_completer;
NamespaceMetaMap m_namespace_maps;
MapCompleter *m_map_completer;
ObjCInterfaceMetaMap m_objc_interface_maps;
};
typedef lldb::SharedPtr<ASTContextMetadata>::Type ASTContextMetadataSP;

View File

@@ -22,6 +22,8 @@
#include "lldb/Expression/ClangPersistentVariables.h"
#include "lldb/Expression/ASTResultSynthesizer.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Target/Target.h"
using namespace llvm;
using namespace clang;
@@ -29,13 +31,11 @@ using namespace lldb_private;
ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
TypeFromUser desired_type,
ASTContext &scratch_ast_context,
ClangPersistentVariables &persistent_vars) :
Target &target) :
m_ast_context (NULL),
m_passthrough (passthrough),
m_passthrough_sema (NULL),
m_scratch_ast_context (scratch_ast_context),
m_persistent_vars (persistent_vars),
m_target (target),
m_sema (NULL),
m_desired_type (desired_type)
{
@@ -442,14 +442,12 @@ ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D)
if (log)
log->Printf ("Recording persistent type %s\n", name_cs.GetCString());
Decl *D_scratch = ClangASTContext::CopyDecl(&m_scratch_ast_context,
m_ast_context,
D);
Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(),
m_ast_context,
D);
TypeDecl *TD_scratch = dyn_cast<TypeDecl>(D_scratch);
if (TD_scratch)
m_persistent_vars.RegisterPersistentType(name_cs, TD_scratch);
if (TypeDecl *TypeDecl_scratch = dyn_cast<TypeDecl>(D_scratch))
m_target.GetPersistentVariables().RegisterPersistentType(name_cs, TypeDecl_scratch);
}
void

View File

@@ -463,29 +463,11 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
SymbolContext null_sc;
if (module_sp && namespace_decl)
{
module_sp->FindTypes(null_sc, name, &namespace_decl, true, 1, types);
}
else if(name != id_name && name != Class_name)
{
m_target->GetImages().FindTypes (null_sc, name, true, 1, types);
if (!types.GetSize())
{
lldb::ProcessSP process = m_target->GetProcessSP();
if (process && process->GetObjCLanguageRuntime())
{
SymbolVendor *objc_symbol_vendor = process->GetObjCLanguageRuntime()->GetSymbolVendor();
objc_symbol_vendor->FindTypes(null_sc, name, NULL, true, 1, types);
}
}
}
m_target->GetImages().FindTypes(null_sc, name, true, 1, types);
else
{
break;
}
if (types.GetSize())
{
@@ -501,13 +483,15 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
(name_string ? name_string : "<anonymous>"));
}
void *copied_type = GuardedCopyType(m_ast_context, type_sp->GetClangAST(), type_sp->GetClangFullType());
if (!copied_type)
{
if (log)
log->Printf("ClangExpressionDeclMap::BuildIntegerVariable - Couldn't export the type for a constant integer result");
log->Printf(" CAS::FEVD[%u] - Couldn't export the type for a constant integer result",
current_id);
break;
}
@@ -534,6 +518,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
return;
StreamString ss;
if (decl_name.isObjCZeroArgSelector())
{
ss.Printf("%s", decl_name.getAsString().c_str());
@@ -565,6 +550,90 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
interface_decl->getNameAsString().c_str(),
selector_name.AsCString());
ClangASTImporter::ObjCInterfaceMapSP interface_map = m_ast_importer->GetObjCInterfaceMap(interface_decl);
if (interface_map)
{
for (ClangASTImporter::ObjCInterfaceMap::iterator i = interface_map->begin(), e = interface_map->end();
i != e;
++i)
{
lldb::clang_type_t backing_type = i->GetOpaqueQualType();
if (!backing_type)
continue;
QualType backing_qual_type = QualType::getFromOpaquePtr(backing_type);
const ObjCInterfaceType *backing_interface_type = dyn_cast<ObjCInterfaceType>(backing_qual_type.getTypePtr());
if (!backing_interface_type)
continue;
const ObjCInterfaceDecl *backing_interface_decl = backing_interface_type->getDecl();
if (!backing_interface_decl)
continue;
if (backing_interface_decl->decls_begin() == backing_interface_decl->decls_end())
continue; // don't waste time creating a DeclarationName here
clang::ASTContext &backing_ast_context = backing_interface_decl->getASTContext();
llvm::SmallVector<clang::IdentifierInfo *, 3> selector_components;
if (decl_name.isObjCZeroArgSelector())
{
selector_components.push_back (&backing_ast_context.Idents.get(decl_name.getAsString().c_str()));
}
else if (decl_name.isObjCOneArgSelector())
{
selector_components.push_back (&backing_ast_context.Idents.get(decl_name.getAsString().c_str()));
}
else
{
clang::Selector sel = decl_name.getObjCSelector();
for (unsigned i = 0, e = sel.getNumArgs();
i != e;
++i)
{
llvm::StringRef r = sel.getNameForSlot(i);
selector_components.push_back (&backing_ast_context.Idents.get(r.str().c_str()));
}
}
Selector backing_selector = backing_interface_decl->getASTContext().Selectors.getSelector(selector_components.size(), selector_components.data());
DeclarationName backing_decl_name = DeclarationName(backing_selector);
DeclContext::lookup_const_result lookup_result = backing_interface_decl->lookup(backing_decl_name);
if (lookup_result.first == lookup_result.second)
continue;
ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(*lookup_result.first);
if (!method_decl)
continue;
Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &backing_ast_context, *lookup_result.first);
ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl> (copied_decl);
if (!copied_method_decl)
continue;
if (log)
{
ASTDumper dumper((Decl*)copied_method_decl);
log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString());
}
context.AddNamedDecl(copied_method_decl);
}
}
SymbolContextList sc_list;
const bool include_symbols = false;
@@ -614,7 +683,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
if (log)
{
ASTDumper dumper((Decl*)copied_method_decl);
log->Printf(" CAS::FOMD[%d] found %s", current_id, dumper.GetCString());
log->Printf(" CAS::FOMD[%d] found (in debug info) %s", current_id, dumper.GetCString());
}
context.AddNamedDecl(copied_method_decl);
@@ -777,6 +846,29 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac
}
}
void
ClangASTSource::CompleteObjCInterfaceMap (ClangASTImporter::ObjCInterfaceMapSP &objc_interface_map,
const ConstString &name) const
{
SymbolContext null_sc;
TypeList types;
m_target->GetImages().FindTypes(null_sc, name, true, UINT32_MAX, types);
for (uint32_t i = 0, e = types.GetSize();
i != e;
++i)
{
lldb::TypeSP mapped_type_sp = types.GetTypeAtIndex(i);
if (!mapped_type_sp || !mapped_type_sp->GetClangFullType())
continue;
objc_interface_map->push_back (ClangASTType(mapped_type_sp->GetClangAST(), mapped_type_sp->GetClangFullType()));
}
}
NamespaceDecl *
ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls)
{

View File

@@ -895,8 +895,12 @@ ClangExpressionDeclMap::WriteTarget (lldb_private::Value &value,
return err.Success();
}
case Value::eValueTypeHostAddress:
memcpy ((void *)value.GetScalar().ULongLong(), data, length);
return true;
{
if (value.GetScalar().ULongLong() == 0 || data == NULL)
return false;
memcpy ((void *)value.GetScalar().ULongLong(), data, length);
return true;
}
case Value::eValueTypeScalar:
return false;
}
@@ -2474,7 +2478,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
if (!ptype_type_decl)
break;
Decl *parser_ptype_decl = ClangASTContext::CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl);
Decl *parser_ptype_decl = m_ast_importer->CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl);
if (!parser_ptype_decl)
break;

View File

@@ -92,8 +92,7 @@ ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
if (!m_result_synthesizer.get())
m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough,
m_desired_type,
*m_target->GetScratchClangASTContext()->getASTContext(),
m_target->GetPersistentVariables()));
*m_target));
return m_result_synthesizer.get();
}

View File

@@ -71,6 +71,30 @@ ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast,
return NULL;
}
clang::Decl *
ClangASTImporter::DeportDecl (clang::ASTContext *dst_ctx,
clang::ASTContext *src_ctx,
clang::Decl *decl)
{
clang::Decl *result = CopyDecl(dst_ctx, src_ctx, decl);
if (!result)
return NULL;
ClangASTContext::GetCompleteDecl (src_ctx, decl);
MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
if (minion_sp && isa<TagDecl>(decl))
minion_sp->ImportDefinition(decl);
ASTContextMetadataSP to_context_md = GetContextMetadata(dst_ctx);
to_context_md->m_origins.erase(result);
return result;
}
void
ClangASTImporter::CompleteTagDecl (clang::TagDecl *decl)
{
@@ -175,7 +199,7 @@ ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl)
context_md->m_map_completer->CompleteNamespaceMap (new_map, ConstString(namespace_string.c_str()), parent_map);
}
RegisterNamespaceMap (decl, new_map);
context_md->m_namespace_maps[decl] = new_map;
}
void
@@ -205,11 +229,43 @@ ClangASTImporter::ForgetSource (clang::ASTContext *dst_ast, clang::ASTContext *s
}
}
ClangASTImporter::NamespaceMapCompleter::~NamespaceMapCompleter ()
ClangASTImporter::MapCompleter::~MapCompleter ()
{
return;
}
ClangASTImporter::ObjCInterfaceMapSP
ClangASTImporter::GetObjCInterfaceMap (const clang::ObjCInterfaceDecl *decl)
{
ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
ObjCInterfaceMetaMap &objc_interface_maps = context_md->m_objc_interface_maps;
ObjCInterfaceMetaMap::iterator iter = objc_interface_maps.find(decl);
if (iter != objc_interface_maps.end())
return iter->second;
else
return ObjCInterfaceMapSP();
}
void
ClangASTImporter::BuildObjCInterfaceMap (const clang::ObjCInterfaceDecl *decl)
{
ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
ObjCInterfaceMapSP new_map(new ObjCInterfaceMap);
if (context_md->m_map_completer)
{
std::string namespace_string = decl->getDeclName().getAsString();
context_md->m_map_completer->CompleteObjCInterfaceMap(new_map, ConstString(namespace_string.c_str()));
}
context_md->m_objc_interface_maps[decl] = new_map;
}
clang::Decl
*ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
{
@@ -256,6 +312,8 @@ clang::Decl
}
else
{
to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
if (log)
log->Printf(" [ClangASTImporter] Decl has no origin information in (ASTContext*)%p",
&from->getASTContext());
@@ -313,6 +371,8 @@ clang::Decl
{
ObjCInterfaceDecl *to_interface_decl = dyn_cast<ObjCInterfaceDecl>(to);
m_master.BuildObjCInterfaceMap(to_interface_decl);
to_interface_decl->setHasExternalLexicalStorage();
to_interface_decl->setHasExternalVisibleStorage();
@@ -320,7 +380,7 @@ clang::Decl
to_interface_decl->completedForwardDecl();
to_interface_decl->setExternallyCompleted();
if (log)
log->Printf(" [ClangASTImporter] To is an ObjCInterfaceDecl - attributes %s%s%s",
(to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""),