Skip to content
Snippets Groups Projects
Commit e5a75f19 authored by Axel Naumann's avatar Axel Naumann
Browse files

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
parent fff1d00b
No related branches found
No related tags found
No related merge requests found
......@@ -432,7 +432,10 @@ void TCling__UpdateListsOnCommitted(const cling::Transaction &T) {
// The above might trigger more decls to be deserialized.
// Thus the iteration over the deserialized decls must be last.
std::vector<const void*>& DeserDecls = ((TCling*)gCling)->GetDeserializedDecls();
std::vector<const void*> DeserDecls;
// HandleNewDecl() might cause a transaction; prevent it from handling
// our DeserDecls.
DeserDecls.swap(((TCling*)gCling)->GetDeserializedDecls());
if (!DeserDecls.empty()) {
for (size_t i = 0; i < DeserDecls.size(); ++i) {
if (TransactionDeclSet.find(DeserDecls[i])
......@@ -451,8 +454,6 @@ void TCling__UpdateListsOnCommitted(const cling::Transaction &T) {
((TCling*)gCling)->UpdateListOfDataMembers(*I);
}
}
DeserDecls.clear();
}
extern "C"
......
......@@ -387,9 +387,11 @@ bool TClingCallbacks::tryInjectImplicitAutoKeyword(LookupResult &R, Scope *S) {
// The callback is used to update the list of globals in ROOT.
//
void TClingCallbacks::TransactionCommitted(const Transaction &T) {
if (!T.size())
return;
if (fFirstRun) {
// Even empty transactions must go through; any transactio even empty
// will flush the deserialized decls into Meta.
//if (!T.size())
// return;
if (fFirstRun && !T.empty()) {
// Before setting up the callbacks register what cling have seen during init.
cling::Transaction TPrev(T.getCompilationOpts(), T.getModule());
clang::DeclGroupRef TDRG = T.getFirstDecl();
......
......@@ -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.
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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,9 +333,8 @@ namespace cling {
rollbackTransaction(T);
return;
}
}
T->setState(Transaction::kCommitting);
} else
T->setState(Transaction::kCommitting);
InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks();
......
......@@ -871,6 +871,12 @@ namespace cling {
}
}
clang::ASTDeserializationListener*
Interpreter::getASTDeserializationListener() const {
return m_CallbackAdaptor;
}
const Transaction* Interpreter::getFirstTransaction() const {
return m_IncrParser->getFirstTransaction();
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment