Added test for MultipleInterpreters, and some changes.

This commit is contained in:
Elisavet Sakellari 2016-01-11 15:17:58 +01:00 committed by sftnight
parent 8f51dd1617
commit 4ac0a10a3e
4 changed files with 80 additions and 32 deletions

View File

@ -9,8 +9,6 @@
#ifndef CLING_ASTIMPORTSOURCE_H
#define CLING_ASTIMPORTSOURCE_H
#include "cling/Interpreter/Interpreter.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Sema.h"
#include "clang/AST/ASTContext.h"
@ -28,6 +26,10 @@ namespace clang {
class Sema;
}
namespace cling {
class Interpreter;
}
namespace cling {
namespace utils {
@ -56,20 +58,7 @@ namespace cling {
public:
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;
}
cling::Interpreter *child_interpreter);
~ASTImportSource() { };

View File

@ -25,6 +25,7 @@
#include "cling/Interpreter/Transaction.h"
#include "cling/Interpreter/Value.h"
#include "cling/Utils/AST.h"
#include "cling/Utils/ASTImportSource.h"
#include "cling/Interpreter/AutoloadCallback.h"
#include "clang/AST/ASTContext.h"
@ -233,8 +234,25 @@ namespace cling {
Interpreter::Interpreter(Interpreter &parentInterpreter, int argc, const char* const *argv,
const char* llvmdir /*= 0*/, bool noRuntime) :
Interpreter(argc, argv, llvmdir, noRuntime, /* isChildInterp */ true) {
// Do the "setup" of the connection between this interpreter and
// its parent interpreter.
// The "bridge" between the interpreters.
utils::ASTImportSource *myExternalSource =
new utils::ASTImportSource(&parentInterpreter, this);
llvm::IntrusiveRefCntPtr <ExternalASTSource>
astContextExternalSource(myExternalSource);
this->getCI()->getASTContext().ExternalSource.resetWithoutRelease();
this->getCI()->getASTContext().setExternalSource(astContextExternalSource);
// Inform the Translation Unit Decl of I2 that it has to
// search somewhere else to find the declarations.
this->getCI()->getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage();
// Give my IncrementalExecutor a pointer to the Incremental executor
// of the parent Interpreter.
// of the parent Interpreter.
m_Executor->setExternalIncrementalExecutor(parentInterpreter.m_Executor.get());
}

View File

@ -1,10 +1,27 @@
#include "cling/Utils/ASTImportSource.h"
#include "cling/Interpreter/Interpreter.h"
using namespace clang;
namespace cling {
namespace utils {
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,
@ -17,13 +34,6 @@ namespace cling {
// once clang supports the import of function templates.
if (!(declToImport->isFunctionOrFunctionTemplate() && declToImport->isTemplateDecl())) {
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.getAsString()] = parentDeclName;
@ -41,16 +51,13 @@ namespace cling {
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.getAsString()] = parentDeclName;
// (Except for the case when it is a function declaration,
// because we may want to search again for functions
// with the same name (function overloading). )
if (!importedDeclContext->isFunctionOrMethod())
m_DeclName_map[childDeclName.getAsString()] = 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.

View File

@ -0,0 +1,34 @@
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------
// RUN: cat %s | %cling 2>&1 | FileCheck %s
// Test to check the functionality of the multiple interpreters.
// Create a "child" interpreter and use gCling as its "parent".
#include "cling/Interpreter/Interpreter.h"
#include <iostream>
const char * const argV = "cling";
cling::Interpreter *ChildInterp = new cling::Interpreter(*gCling, 1, &argV);
//declare something in the parent interpreter
gCling->declare("void foo(){ std::cout << \"foo(void)\" << std::endl; }");
//then execute it from the child interpreter
ChildInterp->execute("foo()");
//CHECK:foo(void)
//check if function overloading works
gCling->declare("void foo(int i){ std::cout << \"foo(int)\" << std::endl; }");
ChildInterp->execute("foo(1)");
//CHECK:foo(int)
.q