I made the ClangASTImporter owned by the target

rather than individually on behalf of each
ASTContext.  This allows the ASTImporter to know
about all containers of types, which will let it
be smarter about forwarding information about
type origins.  That means that the following
sequence of steps will be possible (after a few
more changes):

- Import a type from a Module's ASTContext into
  an expression parser ASTContext, tracking its
  origin information -- this works now.

- Because the result of the expression uses that
  type, import it from the expression parser
  ASTContext into the Target's scratch AST
  context, forwarding the origin information --
  this needs to be added.

- For a later expression that uses the result,
  import the type from the Target's scratch AST
  context, still forwarding origin information
  -- this also needs to be added.

- Use the intact origin information to complete
  the type as needed -- this works now if the
  origin information is present.

To this end, I made the following changes:

- ASTImporter top-level copy functions now
  require both a source and a destination AST
  context parameter.

- The ASTImporter now knows how to purge
  records related to an ASTContext that is
  going away.

- The Target now owns and creates the ASTImporter
  whenever the main executable changes or (in the
  absence of a main executable) on demand.

llvm-svn: 144802
This commit is contained in:
Sean Callanan 2011-11-16 18:20:47 +00:00
parent 8855ff61cb
commit 686b2319e5
7 changed files with 96 additions and 53 deletions

View File

@ -50,6 +50,7 @@ public:
m_ast_context (NULL),
m_active_lookups ()
{
m_ast_importer = m_target->GetClangASTImporter();
}
//------------------------------------------------------------------
@ -71,13 +72,6 @@ public:
void InstallASTContext (clang::ASTContext *ast_context)
{
if (!m_ast_importer.get() ||
m_ast_importer->TargetASTContext() != ast_context)
{
m_ast_importer.reset(new ClangASTImporter(ast_context));
m_ast_importer->InstallMapCompleter(*this);
}
m_ast_context = ast_context;
}
@ -329,8 +323,8 @@ protected:
bool m_lookups_enabled;
const lldb::TargetSP m_target; ///< The target to use in finding variables and types.
clang::ASTContext *m_ast_context; ///< The parser's AST context, for copying types into
std::auto_ptr<ClangASTImporter> m_ast_importer;
clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for.
ClangASTImporter *m_ast_importer; ///< The target's AST importer.
std::set<const char *> m_active_lookups;
};

View File

@ -28,24 +28,19 @@ namespace lldb_private {
class ClangASTImporter
{
public:
ClangASTImporter (clang::ASTContext *target_ctx) :
m_file_manager(clang::FileSystemOptions()),
m_target_ctx(target_ctx)
ClangASTImporter () :
m_file_manager(clang::FileSystemOptions())
{
}
clang::ASTContext *
TargetASTContext ()
{
return m_target_ctx;
}
clang::QualType
CopyType (clang::ASTContext *src_ctx,
CopyType (clang::ASTContext *dst_ctx,
clang::ASTContext *src_ctx,
clang::QualType type);
clang::Decl *
CopyDecl (clang::ASTContext *src_ctx,
CopyDecl (clang::ASTContext *dst_ctx,
clang::ASTContext *src_ctx,
clang::Decl *decl);
void
@ -92,6 +87,8 @@ public:
NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl);
void BuildNamespaceMap (const clang::NamespaceDecl *decl);
void PurgeMaps (clang::ASTContext *dest_ast_ctx);
private:
struct DeclOrigin
{
@ -130,13 +127,13 @@ private:
{
public:
Minion (ClangASTImporter &master,
clang::ASTContext *source_ctx,
bool minimal) :
clang::ASTImporter(*master.m_target_ctx,
clang::ASTContext *target_ctx,
clang::ASTContext *source_ctx) :
clang::ASTImporter(*target_ctx,
master.m_file_manager,
*source_ctx,
master.m_file_manager,
minimal),
true /*minimal*/),
m_master(master),
m_source_ctx(source_ctx)
{
@ -149,24 +146,40 @@ private:
};
typedef lldb::SharedPtr<Minion>::Type MinionSP;
typedef std::map<clang::ASTContext *, MinionSP> MinionMap;
struct MinionSpec
{
clang::ASTContext *dst;
clang::ASTContext *src;
MinionSpec (clang::ASTContext *_dst,
clang::ASTContext *_src) :
dst(_dst),
src(_src)
{
}
bool operator<(const MinionSpec &rhs) const
{
if (dst < rhs.dst)
return true;
if (dst == rhs.dst && src < rhs.src)
return true;
return false;
}
};
typedef std::map<MinionSpec, MinionSP> MinionMap;
MinionSP
GetMinion (clang::ASTContext *source_ctx, bool minimal)
GetMinion (clang::ASTContext *target_ctx, clang::ASTContext *source_ctx)
{
MinionMap *minions;
MinionSpec spec(target_ctx, source_ctx);
minimal = true; // This override is temporary, while I sort out the attendant issues.
if (m_minions.find(spec) == m_minions.end())
m_minions[spec] = MinionSP(new Minion(*this, target_ctx, source_ctx));
if (minimal)
minions = &m_minimal_minions;
else
minions = &m_minions;
if (minions->find(source_ctx) == minions->end())
(*minions)[source_ctx] = MinionSP(new Minion(*this, source_ctx, minimal));
return (*minions)[source_ctx];
return m_minions[spec];
}
DeclOrigin
@ -185,9 +198,7 @@ private:
NamespaceMetaMap m_namespace_maps;
NamespaceMapCompleter *m_map_completer;
clang::FileManager m_file_manager;
clang::ASTContext *m_target_ctx;
MinionMap m_minions;
MinionMap m_minimal_minions;
OriginMap m_origins;
};

View File

@ -801,6 +801,9 @@ public:
ClangASTContext *
GetScratchClangASTContext();
ClangASTImporter *
GetClangASTImporter();
const char *
GetExpressionPrefixContentsAsCString ();
@ -1054,6 +1057,7 @@ protected:
PathMappingList m_image_search_paths;
std::auto_ptr<ClangASTContext> m_scratch_ast_context_ap;
std::auto_ptr<ClangASTSource> m_scratch_ast_source_ap;
std::auto_ptr<ClangASTImporter> m_ast_importer_ap;
ClangPersistentVariables m_persistent_variables; ///< These are the persistent variables associated with this process for the expression parser.
SourceManager m_source_manager;

View File

@ -41,6 +41,7 @@ class BreakpointSiteList;
class Broadcaster;
class CPPLanguageRuntime;
class ClangASTContext;
class ClangASTImporter;
class ClangASTSource;
class ClangASTType;
class ClangNamespaceDecl;

View File

@ -24,6 +24,7 @@ using namespace lldb_private;
ClangASTSource::~ClangASTSource()
{
m_ast_importer->PurgeMaps(m_ast_context);
}
void
@ -249,7 +250,7 @@ ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
log->Printf(" FELD[%d] Adding lexical decl %s", current_id, ast_dumper.GetCString());
}
Decl *copied_decl = m_ast_importer->CopyDecl(original_ctx, decl);
Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, original_ctx, decl);
decls.push_back(copied_decl);
}
@ -551,7 +552,7 @@ ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
if (found_interface_decl->getName() == interface_decl->getName())
{
Decl *copied_decl = m_ast_importer->CopyDecl(&method_decl->getASTContext(), method_decl);
Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl);
if (!copied_decl)
continue;
@ -610,7 +611,7 @@ ClangASTSource::FindObjCPropertyDecls (NameSearchContext &context)
if (!property_decl)
return;
Decl *copied_decl = m_ast_importer->CopyDecl(orig_ast_ctx, property_decl);
Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, orig_ast_ctx, property_decl);
if (!copied_decl)
return;
@ -734,7 +735,7 @@ ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::Name
const ClangNamespaceDecl &namespace_decl = namespace_decls->begin()->second;
Decl *copied_decl = m_ast_importer->CopyDecl(namespace_decl.GetASTContext(), namespace_decl.GetNamespaceDecl());
Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, namespace_decl.GetASTContext(), namespace_decl.GetNamespaceDecl());
NamespaceDecl *copied_namespace_decl = dyn_cast<NamespaceDecl>(copied_decl);
@ -750,7 +751,7 @@ ClangASTSource::GuardedCopyType (ASTContext *dest_context,
{
SetImportInProgress(true);
QualType ret_qual_type = m_ast_importer->CopyType (source_context, QualType::getFromOpaquePtr(clang_type));
QualType ret_qual_type = m_ast_importer->CopyType (m_ast_context, source_context, QualType::getFromOpaquePtr(clang_type));
void *ret = ret_qual_type.getAsOpaquePtr();

View File

@ -19,10 +19,11 @@ using namespace lldb_private;
using namespace clang;
clang::QualType
ClangASTImporter::CopyType (clang::ASTContext *src_ast,
ClangASTImporter::CopyType (clang::ASTContext *dst_ast,
clang::ASTContext *src_ast,
clang::QualType type)
{
MinionSP minion_sp (GetMinion(src_ast, false));
MinionSP minion_sp (GetMinion(dst_ast, src_ast));
if (minion_sp)
return minion_sp->Import(type);
@ -31,15 +32,13 @@ ClangASTImporter::CopyType (clang::ASTContext *src_ast,
}
clang::Decl *
ClangASTImporter::CopyDecl (clang::ASTContext *src_ast,
ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast,
clang::ASTContext *src_ast,
clang::Decl *decl)
{
MinionSP minion_sp;
if (isa<clang::NamespaceDecl>(decl))
minion_sp = GetMinion(src_ast, true);
else
minion_sp = GetMinion(src_ast, false);
minion_sp = GetMinion(dst_ast, src_ast);
if (minion_sp)
{
@ -77,7 +76,7 @@ ClangASTImporter::CompleteTagDecl (clang::TagDecl *decl)
if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
return;
MinionSP minion_sp (GetMinion(decl_origin.ctx, false));
MinionSP minion_sp (GetMinion(&decl->getASTContext(), decl_origin.ctx));
if (minion_sp)
minion_sp->ImportDefinition(decl_origin.decl);
@ -98,7 +97,7 @@ ClangASTImporter::CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface
if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
return;
MinionSP minion_sp (GetMinion(decl_origin.ctx, false));
MinionSP minion_sp (GetMinion(&interface_decl->getASTContext(), decl_origin.ctx));
if (minion_sp)
minion_sp->ImportDefinition(decl_origin.decl);
@ -148,6 +147,18 @@ ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl)
RegisterNamespaceMap (decl, new_map);
}
void
ClangASTImporter::PurgeMaps (clang::ASTContext *dst_ast)
{
for (MinionMap::iterator i = m_minions.begin(); i != m_minions.end(); )
{
if ((*i).first.dst == dst_ast)
m_minions.erase(i++);
else
++i;
}
}
ClangASTImporter::NamespaceMapCompleter::~NamespaceMapCompleter ()
{
return;

View File

@ -61,6 +61,8 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
m_search_filter_sp (),
m_image_search_paths (ImageSearchPathsChanged, this),
m_scratch_ast_context_ap (NULL),
m_scratch_ast_source_ap (NULL),
m_ast_importer_ap (NULL),
m_persistent_variables (),
m_source_manager(*this),
m_stop_hooks (),
@ -173,6 +175,7 @@ Target::Destroy()
m_image_search_paths.Clear(notify);
m_scratch_ast_context_ap.reset();
m_scratch_ast_source_ap.reset();
m_ast_importer_ap.reset();
m_persistent_variables.Clear();
m_stop_hooks.clear();
m_stop_hook_next_id = 0;
@ -797,6 +800,7 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
m_images.Clear();
m_scratch_ast_context_ap.reset();
m_scratch_ast_source_ap.reset();
m_ast_importer_ap.reset();
if (executable_sp.get())
{
@ -837,6 +841,7 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
}
}
m_ast_importer_ap.reset(new ClangASTImporter());
}
UpdateInstanceName();
@ -865,6 +870,8 @@ Target::SetArchitecture (const ArchSpec &arch_spec)
ModuleSP executable_sp = GetExecutableModule ();
m_images.Clear();
m_scratch_ast_context_ap.reset();
m_scratch_ast_source_ap.reset();
m_ast_importer_ap.reset();
// Need to do something about unsetting breakpoints.
if (executable_sp)
@ -1342,6 +1349,20 @@ Target::GetScratchClangASTContext()
return m_scratch_ast_context_ap.get();
}
ClangASTImporter *
Target::GetClangASTImporter()
{
ClangASTImporter *ast_importer = m_ast_importer_ap.get();
if (!ast_importer)
{
ast_importer = new ClangASTImporter();
m_ast_importer_ap.reset(ast_importer);
}
return ast_importer;
}
void
Target::SettingsInitialize ()
{