For Decls coming from a parsed file that describes the content of a library:

the callbacks must be triggered for those, too.
As they are not part of a transaction (think "module") they are now sent to the deserialization listener.
This can be removed once the modules work.

Set the state of the transaction to Committing before the static init - which might trigger more decls even though CodeGen has been run over the decls.

Forward DeclCollector::HandleInterestingDecl() to DeclCollector::HandleTopLevelDecl() for decls from the AST reader / from headers describing libraries.

Empty transactions must be passed to TCling; they trigger the sending of deserialized decls to ROOT/Meta.

Don't start TCling's artificial TU Transaction if the transaction coming in is empty - we need a decl to get the ASTContext.

Swap the deserialized decls before handling them in TCling, such that nested calls don't see the same decls again.


git-svn-id: http://root.cern.ch/svn/root/trunk@49197 27541ba8-7e3a-0410-8455-c3a389f83636
This commit is contained in:
Axel Naumann 2013-04-10 15:15:49 +00:00
parent 376aecc88b
commit 48b4a4e934
5 changed files with 43 additions and 11 deletions

View File

@ -32,6 +32,7 @@ namespace llvm {
namespace clang {
class ASTContext;
class ASTDeserializationListener;
class CodeGenerator;
class CompilerInstance;
class Decl;
@ -648,6 +649,10 @@ namespace cling {
const InterpreterCallbacks* getCallbacks() const {return m_Callbacks.get();}
InterpreterCallbacks* getCallbacks() { return m_Callbacks.get(); }
// FIXME: remove once modules are there; see
// DeclCollector::HandleTopLevelDecl().
clang::ASTDeserializationListener* getASTDeserializationListener() const;
const Transaction* getFirstTransaction() const;
///\brief Gets the address of an existing global and whether it was JITted.

View File

@ -6,11 +6,13 @@
#include "DeclCollector.h"
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/CodeGen/ModuleBuilder.h"
@ -58,8 +60,16 @@ namespace cling {
// Recurse over decls inside the namespace, like
// CodeGenModule::EmitNamespace() does.
HandleTopLevelDecl(DeclGroupRef(*IN));
} else if (!shouldIgnoreDeclFromASTReader(*I))
} else if (!shouldIgnoreDeclFromASTReader(*I)) {
m_CodeGen->HandleTopLevelDecl(DeclGroupRef(*I));
// FIXME: once modules are there this is not needed anymore.
// it is used to simulate modules and the ASTDeserializationListener
// for sources that are included to describe the library that was
// built from the sources (ACLiC).
if (!(*I)->isFromASTFile() && m_Interp->getASTDeserializationListener())
m_Interp->getASTDeserializationListener()->DeclRead(0, *I);
}
}
return true;
}
@ -73,12 +83,7 @@ namespace cling {
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
// pipe it directly to codegen.
if (comesFromASTReader(DGR)) {
if (m_CodeGen) {
for (DeclGroupRef::iterator I = DGR.begin(), E = DGR.end();
I != E; ++I)
if (!shouldIgnoreDeclFromASTReader(*I))
m_CodeGen->HandleTopLevelDecl(DeclGroupRef(*I));
}
HandleTopLevelDecl(DGR);
return;
}

View File

@ -18,6 +18,7 @@ namespace clang {
namespace cling {
class Interpreter;
class Transaction;
///\brief Collects declarations and fills them in cling::Transaction.
@ -34,6 +35,11 @@ namespace cling {
/// special handling. Eg. deserialized declarations.
clang::CodeGenerator* m_CodeGen; // we do not own.
///\brief Interpreter feeding into the DeclCollector. Only used for
/// a temporary workaround until modules work.
/// FIXME: remove once modules work.
cling::Interpreter* m_Interp; // we do not own.
///\brief Test whether the first decl of the DeclGroupRef comes from an AST
/// file.
bool comesFromASTReader(clang::DeclGroupRef DGR) const;
@ -44,13 +50,17 @@ namespace cling {
bool shouldIgnoreDeclFromASTReader(const clang::Decl* D) const;
public:
DeclCollector() : m_CurTransaction(0), m_CodeGen(0) {}
DeclCollector() :
m_CurTransaction(0), m_CodeGen(0), m_Interp(0) {}
virtual ~DeclCollector();
// FIXME: Gross hack, which should disappear when we move some of the
// initialization happening in the IncrementalParser to the CIFactory.
void setCodeGen(clang::CodeGenerator* codeGen) { m_CodeGen = codeGen; }
// FIXME: Gross hack, which should disappear when m_Interp can go.
void setInterpreter(cling::Interpreter* Interp) { m_Interp = Interp; }
/// \{
/// \name ASTConsumer overrides

View File

@ -54,6 +54,7 @@ namespace cling {
m_Consumer = dyn_cast<DeclCollector>(&CI->getASTConsumer());
assert(m_Consumer && "Expected ChainedConsumer!");
m_Consumer->setInterpreter(interp);
m_CI.reset(CI);
@ -317,8 +318,14 @@ namespace cling {
else
llvm_unreachable("We shouldn't have decl without call info.");
}
getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext());
// The static initializers might run anything and can thus cause more
// decls that need to end up in a transaction. But this one is done
// with CodeGen...
T->setState(Transaction::kCommitting);
// run the static initializers that came from codegenning
if (m_Interpreter->runStaticInitializersOnce()
>= Interpreter::kExeFirstError) {
@ -326,8 +333,7 @@ namespace cling {
rollbackTransaction(T);
return;
}
}
} else
T->setState(Transaction::kCommitting);
InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks();

View File

@ -871,6 +871,12 @@ namespace cling {
}
}
clang::ASTDeserializationListener*
Interpreter::getASTDeserializationListener() const {
return m_CallbackAdaptor;
}
const Transaction* Interpreter::getFirstTransaction() const {
return m_IncrParser->getFirstTransaction();
}