Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import only the original declaration of a namespace. +Test for names… #167

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
27 changes: 24 additions & 3 deletions interpreter/cling/include/cling/Interpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,13 @@ namespace cling {
///
void IncludeCRuntime();

///\brier The target constructor to be called from both the
///\brief The target constructor to be called from both the
/// delegating constructors.
///
///\param[in] isChildInterp - flags whether this is a child or parent
/// interpreter. This information is needed for the creation and
/// initialization of the IncrementalParser.
///
Interpreter(int argc, const char* const *argv,
const char* llvmdir /*= 0*/, bool noRuntime,
bool isChildInterp);
Expand All @@ -293,13 +297,30 @@ namespace cling {
bool noRuntime = false) :
Interpreter(argc, argv, llvmdir, noRuntime, false) { }

///\brief Constructor for child Interpreter.
///\param[in] parentInterpreter - the parent interpreter of this interpreter
///\brief Constructor for child Interpreter in the case of the multiple
/// interpreters.
///
///\param[in] parentInterpreter - This is used for the creation and set
// up of the ASTImportSource and IncrementalExecutor.
///\param[in] argc - no. of args.
///\param[in] argv - arguments passed when driver is invoked.
///\param[in] llvmdir - ???
///\param[in] noRuntime - flag to control the presence of runtime universe
///
///# Symbol Resolution from the execution engine of the child interpreter.
///
/// In order for the child Interpreter to find and execute the correct
/// functions that are defined in the first Interpreter, it holds a pointer
/// to the IncrementalExecutor of its parent. This 'external' IncrementalExecutor
/// has been set during the child interpreter construction.
///
/// When in the child interpreter, the
/// IncrementalExecutor::NotifyLazyFunctionCreators function searches for
/// the address of a missing symbol in the external IncrementalExecutor that
/// has been set during the creation of the interpreter. If it doesn't exist
/// in the external IncrementalExecutor either, it goes to
/// HandleMissingFunction.
///
Interpreter(Interpreter &parentInterpreter,int argc, const char* const *argv,
const char* llvmdir = 0, bool noRuntime = true);

Expand Down
295 changes: 149 additions & 146 deletions interpreter/cling/lib/Interpreter/ASTImportSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,167 +5,170 @@ using namespace clang;

namespace cling {

ASTImportSource::ASTImportSource(cling::Interpreter *parent_interpreter,
cling::Interpreter *child_interpreter) :
ASTImportSource::ASTImportSource(cling::Interpreter *parent_interpreter,
cling::Interpreter *child_interpreter) :
m_parent_Interp(parent_interpreter), m_child_Interp(child_interpreter) {

clang::DeclContext *parentTUDeclContext =
clang::TranslationUnitDecl::castToDeclContext(
m_parent_Interp->getCI()->getASTContext().getTranslationUnitDecl());

clang::DeclContext *childTUDeclContext =
clang::TranslationUnitDecl::castToDeclContext(
m_child_Interp->getCI()->getASTContext().getTranslationUnitDecl());

// Also keep in the map of Decl Contexts the Translation Unit Decl Context
m_DeclContexts_map[childTUDeclContext] = parentTUDeclContext;
}

void ASTImportSource::ImportDecl(Decl *declToImport,
ASTImporter &importer,
DeclarationName &childDeclName,
DeclarationName &parentDeclName,
const DeclContext *childCurrentDeclContext) {

// Don't do the import if we have a Function Template.
// Not supported by clang.
// FIXME: This is also a temporary check. Will be de-activated
// once clang supports the import of function templates.
if (declToImport->isFunctionOrFunctionTemplate() && declToImport->isTemplateDecl())
return;

if (Decl *importedDecl = importer.Import(declToImport)) {
if (NamedDecl *importedNamedDecl = llvm::dyn_cast<NamedDecl>(importedDecl)) {
std::vector < NamedDecl * > declVector{importedNamedDecl};
llvm::ArrayRef < NamedDecl * > FoundDecls(declVector);
SetExternalVisibleDeclsForName(childCurrentDeclContext,
importedNamedDecl->getDeclName(),
FoundDecls);
}
// Put the name of the Decl imported with the
// DeclarationName coming from the parent, in my map.
m_DeclName_map[childDeclName] = parentDeclName;
clang::DeclContext *parentTUDeclContext =
clang::TranslationUnitDecl::castToDeclContext(
m_parent_Interp->getCI()->getASTContext().getTranslationUnitDecl());

clang::DeclContext *childTUDeclContext =
clang::TranslationUnitDecl::castToDeclContext(
m_child_Interp->getCI()->getASTContext().getTranslationUnitDecl());

// Also keep in the map of Decl Contexts the Translation Unit Decl Context
m_childToParentDC[childTUDeclContext] = parentTUDeclContext;
}

void ASTImportSource::ImportDecl(Decl *parentDecl,
ASTImporter &importer,
DeclarationName &childDeclName,
DeclarationName &parentDeclName,
const DeclContext *childCurrentDC) {

// Don't do the import if we have a Function Template.
// Not supported by clang.
// FIXME: This is also a temporary check. Will be de-activated
// once clang supports the import of function templates.
if (parentDecl->isFunctionOrFunctionTemplate()
&& parentDecl->isTemplateDecl())
return;

if (Decl *childDecl = importer.Import(parentDecl)) {
if (NamedDecl *childNamedDecl = llvm::dyn_cast<NamedDecl>(childDecl)) {
std::vector < NamedDecl * > declVector{childNamedDecl};
llvm::ArrayRef < NamedDecl * > FoundDecls(declVector);
SetExternalVisibleDeclsForName(childCurrentDC,
childNamedDecl->getDeclName(),
FoundDecls);
}
// Put the name of the Decl imported with the
// DeclarationName coming from the parent, in my map.
m_childToParentName[childDeclName] = parentDeclName;
}

void ASTImportSource::ImportDeclContext(DeclContext *declContextToImport,
ASTImporter &importer,
DeclarationName &childDeclName,
DeclarationName &parentDeclName,
const DeclContext *childCurrentDeclContext) {

if (DeclContext *importedDeclContext = importer.ImportContext(declContextToImport)) {

importedDeclContext->setHasExternalVisibleStorage(true);

if (NamedDecl *importedNamedDecl = llvm::dyn_cast<NamedDecl>(importedDeclContext)) {
std::vector < NamedDecl * > declVector{importedNamedDecl};
llvm::ArrayRef < NamedDecl * > FoundDecls(declVector);
SetExternalVisibleDeclsForName(childCurrentDeclContext,
importedNamedDecl->getDeclName(),
FoundDecls);
}
// Put the name of the DeclContext imported with the
// DeclarationName coming from the parent, in my map.
m_DeclName_map[childDeclName] = parentDeclName;

// And also put the declaration context I found from the parent Interpreter
// in the map of the child Interpreter to have it for the future.
m_DeclContexts_map[importedDeclContext] = declContextToImport;
}
}

void ASTImportSource::ImportDeclContext(DeclContext *parentDC,
ASTImporter &importer,
DeclarationName &childDeclName,
DeclarationName &parentDeclName,
const DeclContext *childCurrentDC) {

// If this declContext is a namespace, import only its original declaration.
if (NamespaceDecl *namespaceDecl
= llvm::dyn_cast<NamespaceDecl>(parentDC)) {
parentDC = namespaceDecl->getOriginalNamespace();
}

bool ASTImportSource::Import(DeclContext::lookup_result lookup_result,
ASTContext &from_ASTContext,
ASTContext &to_ASTContext,
const DeclContext *childCurrentDeclContext,
DeclarationName &childDeclName,
DeclarationName &parentDeclName) {

// Prepare to import the Decl(Context) we found in the
// child interpreter by getting the file managers from
// each interpreter.
FileManager &child_FM = m_child_Interp->getCI()->getFileManager();
FileManager &parent_FM = m_parent_Interp->getCI()->getFileManager();

// Clang's ASTImporter
ASTImporter importer(to_ASTContext, child_FM,
from_ASTContext, parent_FM,
/*MinimalImport : ON*/ true);

for (DeclContext::lookup_iterator I = lookup_result.begin(),
E = lookup_result.end();
I != E; ++I) {
// Check if this Name we are looking for is
// a DeclContext (for example a Namespace, function etc.).
if (DeclContext *declContextToImport = llvm::dyn_cast<DeclContext>(*I)) {

ImportDeclContext(declContextToImport, importer, childDeclName,
parentDeclName, childCurrentDeclContext);

} else if (Decl *declToImport = llvm::dyn_cast<Decl>(*I)) {

// else it is a Decl
ImportDecl(declToImport, importer, childDeclName,
parentDeclName, childCurrentDeclContext);
}
}
return true;
}
if (DeclContext *childDC = importer.ImportContext(parentDC)) {
childDC->setHasExternalVisibleStorage(true);

///\brief This is the most important function of the class ASTImportSource
/// since from here initiates the lookup and import part of the missing
/// Decl(s) (Contexts).
///
bool ASTImportSource::FindExternalVisibleDeclsByName(
const DeclContext *childCurrentDeclContext, DeclarationName childDeclName) {

assert(childCurrentDeclContext->hasExternalVisibleStorage() &&
"DeclContext has no visible decls in storage");

//Check if we have already found this declaration Name before
DeclarationName parentDeclName;
std::map<clang::DeclarationName,
clang::DeclarationName>::iterator II = m_DeclName_map.find(childDeclName);
if (II != m_DeclName_map.end()) {
parentDeclName = II->second;
} else {
// Get the identifier info from the parent interpreter
// for this Name.
llvm::StringRef name(childDeclName.getAsString());
IdentifierTable &parentIdentifierTable =
m_parent_Interp->getCI()->getASTContext().Idents;
IdentifierInfo &parentIdentifierInfo = parentIdentifierTable.get(name);
DeclarationName parentDeclNameTemp(&parentIdentifierInfo);
parentDeclName = parentDeclNameTemp;
if (NamedDecl *childNamedDecl = llvm::dyn_cast<NamedDecl>(childDC)) {
std::vector < NamedDecl * > declVector{childNamedDecl};
llvm::ArrayRef < NamedDecl * > FoundDecls(declVector);
SetExternalVisibleDeclsForName(childCurrentDC,
childNamedDecl->getDeclName(),
FoundDecls);
}
// Put the name of the DeclContext imported with the
// DeclarationName coming from the parent, in my map.
m_childToParentName[childDeclName] = parentDeclName;

// Search in the map of the stored Decl Contexts for this
// Decl Context.
std::map<const clang::DeclContext *, clang::DeclContext *>::iterator I;
if ((I = m_DeclContexts_map.find(childCurrentDeclContext))
!= m_DeclContexts_map.end()) {
// If childCurrentDeclContext was found before and is already in the map,
// then do the lookup using the stored pointer.
DeclContext *parentDeclContext = I->second;
// And also put the declaration context I found from the parent Interpreter
// in the map of the child Interpreter to have it for the future.
m_childToParentDC[childDC] = parentDC;
}
}

bool ASTImportSource::Import(DeclContext::lookup_result lookup_result,
ASTContext &from_ASTContext,
ASTContext &to_ASTContext,
const DeclContext *childCurrentDC,
DeclarationName &childDeclName,
DeclarationName &parentDeclName) {
// Prepare to import the Decl(Context) we found in the
// child interpreter by getting the file managers from
// each interpreter.
FileManager &child_FM = m_child_Interp->getCI()->getFileManager();
FileManager &parent_FM = m_parent_Interp->getCI()->getFileManager();

// Clang's ASTImporter
ASTImporter importer(to_ASTContext, child_FM,
from_ASTContext, parent_FM,
/*MinimalImport : ON*/ true);

for (DeclContext::lookup_iterator I = lookup_result.begin(),
E = lookup_result.end();
I != E; ++I) {
// Check if this Name we are looking for is
// a DeclContext (for example a Namespace, function etc.).
if (DeclContext *parentDC = llvm::dyn_cast<DeclContext>(*I)) {

ImportDeclContext(parentDC, importer, childDeclName,
parentDeclName, childCurrentDC);

} else if (Decl *parentDecl = llvm::dyn_cast<Decl>(*I)) {
// else it is a Decl
ImportDecl(parentDecl, importer, childDeclName,
parentDeclName, childCurrentDC);
}
}
return true;
}

///\brief This is the most important function of the class ASTImportSource
/// since from here initiates the lookup and import part of the missing
/// Decl(s) (Contexts).
///
bool ASTImportSource::FindExternalVisibleDeclsByName(
const DeclContext *childCurrentDeclContext, DeclarationName childDeclName) {

assert(childCurrentDeclContext->hasExternalVisibleStorage() &&
"DeclContext has no visible decls in storage");

//Check if we have already found this declaration Name before
DeclarationName parentDeclName;
std::map<clang::DeclarationName,
clang::DeclarationName>::iterator II
= m_childToParentName.find(childDeclName);
if (II != m_childToParentName.end()) {
parentDeclName = II->second;
} else {
// Get the identifier info from the parent interpreter
// for this Name.
llvm::StringRef name(childDeclName.getAsString());
IdentifierTable &parentIdentifierTable =
m_parent_Interp->getCI()->getASTContext().Idents;
IdentifierInfo &parentIdentifierInfo = parentIdentifierTable.get(name);
DeclarationName parentDeclNameTemp(&parentIdentifierInfo);
parentDeclName = parentDeclNameTemp;
}

Decl *fromDeclContext = Decl::castFromDeclContext(parentDeclContext);
// Search in the map of the stored Decl Contexts for this
// Decl Context.
std::map<const clang::DeclContext *, clang::DeclContext *>::iterator I;
if ((I = m_childToParentDC.find(childCurrentDeclContext))
!= m_childToParentDC.end()) {
// If childCurrentDeclContext was found before and is already in the map,
// then do the lookup using the stored pointer.
DeclContext::lookup_result lookup_result =
I->second->lookup(parentDeclName);

// Check if we found this Name in the parent interpreter
if (!lookup_result.empty()) {
// Do the import
Decl *fromDeclContext = Decl::castFromDeclContext(I->second);
ASTContext &from_ASTContext = fromDeclContext->getASTContext();

Decl *toDeclContext = Decl::castFromDeclContext(childCurrentDeclContext);
ASTContext &to_ASTContext = toDeclContext->getASTContext();

DeclContext::lookup_result lookup_result =
parentDeclContext->lookup(parentDeclName);

// Check if we found this Name in the parent interpreter
if (!lookup_result.empty()) {
// Do the import
if (Import(lookup_result, from_ASTContext, to_ASTContext,
childCurrentDeclContext, childDeclName, parentDeclName))
return true;
}
if (Import(lookup_result, from_ASTContext, to_ASTContext,
childCurrentDeclContext, childDeclName, parentDeclName))
return true;
}
return false;
}
return false;
}
} // end namespace cling
Loading