cling/lib/Interpreter/DeclCollector.cpp
Philippe Canal f65616bffe Add assert
2013-08-12 21:38:56 +02:00

172 lines
6.2 KiB
C++

//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author: Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------
#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"
using namespace clang;
namespace cling {
bool DeclCollector::comesFromASTReader(DeclGroupRef DGR) const {
assert(!DGR.isNull() && "DeclGroupRef is Null!");
assert(m_CurTransaction && "No current transaction when deserializing");
if (m_CurTransaction->getCompilationOpts().CodeGenerationForModule)
return true;
// Take the first/only decl in the group.
Decl* D = *DGR.begin();
return D->isFromASTFile();
}
bool DeclCollector::shouldIgnoreDeclFromASTReader(const Decl* D) const {
// Functions that are inlined must be sent to CodeGen - they will not have a
// symbol in the library.
if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
if (D->isFromASTFile())
return !FD->hasBody();
else
return !FD->isInlined();
}
// Don't codegen statics coming in from a module; they are already part of
// the library.
if (const VarDecl* VD = dyn_cast<VarDecl>(D))
if (VD->hasGlobalStorage())
return true;
return false;
}
// pin the vtable here.
DeclCollector::~DeclCollector() {
}
bool DeclCollector::HandleTopLevelDecl(DeclGroupRef DGR) {
// 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 (NamespaceDecl* ND = dyn_cast<NamespaceDecl>(*I)) {
for (NamespaceDecl::decl_iterator IN = ND->decls_begin(),
EN = ND->decls_end(); IN != EN; ++IN)
// Recurse over decls inside the namespace, like
// CodeGenModule::EmitNamespace() does.
HandleTopLevelDecl(DeclGroupRef(*IN));
} 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;
}
Transaction::DelayCallInfo DCI(DGR, Transaction::kCCIHandleTopLevelDecl);
m_CurTransaction->append(DCI);
return true;
}
void DeclCollector::HandleInterestingDecl(DeclGroupRef DGR) {
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
// pipe it directly to codegen.
if (comesFromASTReader(DGR)) {
HandleTopLevelDecl(DGR);
//return;
}
Transaction::DelayCallInfo DCI(DGR, Transaction::kCCIHandleInterestingDecl);
m_CurTransaction->append(DCI);
}
void DeclCollector::HandleTagDeclDefinition(TagDecl* TD) {
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
// pipe it directly to codegen.
if (comesFromASTReader(DeclGroupRef(TD))) {
if (m_CodeGen)
m_CodeGen->HandleTagDeclDefinition(TD);
//return;
}
Transaction::DelayCallInfo DCI(DeclGroupRef(TD),
Transaction::kCCIHandleTagDeclDefinition);
m_CurTransaction->append(DCI);
}
void DeclCollector::HandleVTable(CXXRecordDecl* RD, bool DefinitionRequired) {
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
// pipe it directly to codegen.
if (comesFromASTReader(DeclGroupRef(RD))) {
// FIXME: when is the vtable part of the library?
if (m_CodeGen)
m_CodeGen->HandleVTable(RD, DefinitionRequired);
//return;
}
Transaction::DelayCallInfo DCI(DeclGroupRef(RD),
Transaction::kCCIHandleVTable);
m_CurTransaction->append(DCI);
// Intentional no-op. It comes through Sema::DefineUsedVTables, which
// comes either Sema::ActOnEndOfTranslationUnit or while instantiating a
// template. In our case we will do it on transaction commit, without
// keeping track of used vtables, because we have cases where we bypass the
// clang/AST and directly ask the module so that we have to generate
// everything without extra smartness.
}
void DeclCollector::CompleteTentativeDefinition(VarDecl* VD) {
assert(0 && "Not implemented yet!");
}
void DeclCollector::HandleTranslationUnit(ASTContext& Ctx) {
}
void DeclCollector::HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
// pipe it directly to codegen.
if (comesFromASTReader(DeclGroupRef(D))) {
if (m_CodeGen)
m_CodeGen->HandleCXXImplicitFunctionInstantiation(D);
//return;
}
Transaction::DelayCallInfo DCI(DeclGroupRef(D),
Transaction::kCCIHandleCXXImplicitFunctionInstantiation);
m_CurTransaction->append(DCI);
}
void DeclCollector::HandleCXXStaticMemberVarInstantiation(VarDecl *D) {
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
// pipe it directly to codegen.
if (comesFromASTReader(DeclGroupRef(D))) {
if (m_CodeGen && !shouldIgnoreDeclFromASTReader(D))
m_CodeGen->HandleCXXStaticMemberVarInstantiation(D);
//return;
}
Transaction::DelayCallInfo DCI(DeclGroupRef(D),
Transaction::kCCIHandleCXXStaticMemberVarInstantiation);
m_CurTransaction->append(DCI);
}
} // namespace cling