v5 of patches.

Remaining:
* callfunc issues finding functions
* vtable issues (likely related)
* in stressHistogram: Test  3: Projection with Range for Histograms and Profiles................OK
  Error in <TStreamerInfo::Build>: TProfile, unknown type: EErrorType fErrorMode


git-svn-id: http://root.cern.ch/svn/root/branches/dev/root6-pch@48858 27541ba8-7e3a-0410-8455-c3a389f83636
This commit is contained in:
Axel Naumann 2013-03-11 13:11:15 +00:00
parent 03cac10cfd
commit 77ba6929b0
11 changed files with 647 additions and 182 deletions

View File

@ -1,21 +1,25 @@
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author: Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------
#ifndef CLING_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H
#define CLING_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H
//===--- MultiplexExternalSemaSource.h - External Sema Interface-*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines ExternalSemaSource interface, dispatching to all clients
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SEMA_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H
#define LLVM_CLANG_SEMA_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Weak.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include <utility>
namespace clang {
class CXXConstructorDecl;
class CXXRecordDecl;
class DeclaratorDecl;
@ -27,44 +31,227 @@ namespace clang {
class TypedefNameDecl;
class ValueDecl;
class VarDecl;
}
namespace cling {
/// \brief An abstract interface that should be implemented by
/// external AST sources that also provide information for semantic
/// analysis.
class MultiplexExternalSemaSource : public clang::ExternalSemaSource {
class MultiplexExternalSemaSource : public ExternalSemaSource {
private:
llvm::SmallVector<ExternalSemaSource*, 4> m_Sources; // doesn't own them.
llvm::SmallVector<ExternalSemaSource*, 2> Sources; // doesn't own them.
public:
///\brief Constructs the external source with given elements.
///\brief Constructs a new multiplexing external sema source and appends the
/// given element to it.
///
///\param[in] sources - Array of ExternalSemaSources.
///\param[in] s1 - A non-null (old) ExternalSemaSource.
///\param[in] s2 - A non-null (new) ExternalSemaSource.
///
MultiplexExternalSemaSource(llvm::ArrayRef<ExternalSemaSource*> sources);
MultiplexExternalSemaSource(ExternalSemaSource& s1, ExternalSemaSource& s2);
~MultiplexExternalSemaSource();
///\brief Appends new source to the source list.
///
///\param[in] source - An ExternalSemaSource.
///
void addSource(ExternalSemaSource &source);
//===--------------------------------------------------------------------===//
// ExternalASTSource.
//===--------------------------------------------------------------------===//
/// \brief Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
///
/// This method only needs to be implemented if the AST source ever
/// passes back decl sets as VisibleDeclaration objects.
///
/// The default implementation of this method is a no-op.
virtual Decl *GetExternalDecl(uint32_t ID);
/// \brief Resolve a selector ID into a selector.
///
/// This operation only needs to be implemented if the AST source
/// returns non-zero for GetNumKnownSelectors().
///
/// The default implementation of this method is a no-op.
virtual Selector GetExternalSelector(uint32_t ID);
/// \brief Returns the number of selectors known to the external AST
/// source.
///
/// The default implementation of this method is a no-op.
virtual uint32_t GetNumExternalSelectors();
/// \brief Resolve the offset of a statement in the decl stream into
/// a statement.
///
/// This operation is meant to be used via a LazyOffsetPtr. It only
/// needs to be implemented if the AST source uses methods like
/// FunctionDecl::setLazyBody when building decls.
///
/// The default implementation of this method is a no-op.
virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
/// \brief Resolve the offset of a set of C++ base specifiers in the decl
/// stream into an array of specifiers.
///
/// The default implementation of this method is a no-op.
virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
/// \brief Finds all declarations with the given name in the
/// given context.
///
/// Generally the final step of this method is either to call
/// SetExternalVisibleDeclsForName or to recursively call lookup on
/// the DeclContext after calling SetExternalVisibleDecls.
///
/// The default implementation of this method is a no-op.
virtual DeclContextLookupResult
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
/// \brief Ensures that the table of all visible declarations inside this
/// context is up to date.
///
/// The default implementation of this functino is a no-op.
virtual void completeVisibleDeclsMap(const DeclContext *DC);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
///
/// \param isKindWeWant a predicate function that returns true if the passed
/// declaration kind is one we are looking for. If NULL, all declarations
/// are returned.
///
/// \return an indication of whether the load succeeded or failed.
///
/// The default implementation of this method is a no-op.
virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
bool (*isKindWeWant)(Decl::Kind),
SmallVectorImpl<Decl*> &Result);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext.
///
/// \return true if an error occurred
ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
SmallVectorImpl<Decl*> &Result) {
return FindExternalLexicalDecls(DC, 0, Result);
}
template <typename DeclTy>
ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC,
SmallVectorImpl<Decl*> &Result) {
return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
}
/// \brief Get the decls that are contained in a file in the Offset/Length
/// range. \p Length can be 0 to indicate a point at \p Offset instead of
/// a range.
virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length,
SmallVectorImpl<Decl *> &Decls);
/// \brief Gives the external AST source an opportunity to complete
/// an incomplete type.
virtual void CompleteType(TagDecl *Tag);
/// \brief Gives the external AST source an opportunity to complete an
/// incomplete Objective-C class.
///
/// This routine will only be invoked if the "externally completed" bit is
/// set on the ObjCInterfaceDecl via the function
/// \c ObjCInterfaceDecl::setExternallyCompleted().
virtual void CompleteType(ObjCInterfaceDecl *Class);
/// \brief Loads comment ranges.
virtual void ReadComments();
/// \brief Notify ExternalASTSource that we started deserialization of
/// a decl or type so until FinishedDeserializing is called there may be
/// decls that are initializing. Must be paired with FinishedDeserializing.
///
/// The default implementation of this method is a no-op.
virtual void StartedDeserializing();
/// \brief Notify ExternalASTSource that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.
///
/// The default implementation of this method is a no-op.
virtual void FinishedDeserializing();
/// \brief Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
///
/// The default implementation of this method is a no-op.
virtual void StartTranslationUnit(ASTConsumer *Consumer);
/// \brief Print any statistics that have been gathered regarding
/// the external AST source.
///
/// The default implementation of this method is a no-op.
virtual void PrintStats();
/// \brief Perform layout on the given record.
///
/// This routine allows the external AST source to provide an specific
/// layout for a record, overriding the layout that would normally be
/// constructed. It is intended for clients who receive specific layout
/// details rather than source code (such as LLDB). The client is expected
/// to fill in the field offsets, base offsets, virtual base offsets, and
/// complete object size.
///
/// \param Record The record whose layout is being requested.
///
/// \param Size The final size of the record, in bits.
///
/// \param Alignment The final alignment of the record, in bits.
///
/// \param FieldOffsets The offset of each of the fields within the record,
/// expressed in bits. All of the fields must be provided with offsets.
///
/// \param BaseOffsets The offset of each of the direct, non-virtual base
/// classes. If any bases are not given offsets, the bases will be laid
/// out according to the ABI.
///
/// \param VirtualBaseOffsets The offset of each of the virtual base classes
/// (either direct or not). If any bases are not given offsets, the bases will
/// be laid out according to the ABI.
///
/// \returns true if the record layout was provided, false otherwise.
virtual bool
layoutRecordType(const RecordDecl *Record,
uint64_t &Size, uint64_t &Alignment,
llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets);
/// Return the amount of memory used by memory buffers, breaking down
/// by heap-backed versus mmap'ed memory.
virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
//===--------------------------------------------------------------------===//
// ExternalSemaSource.
//===--------------------------------------------------------------------===//
/// \brief Initialize the semantic source with the Sema instance
/// being used to perform semantic analysis on the abstract syntax
/// tree.
virtual void InitializeSema(clang::Sema& S);
virtual void InitializeSema(Sema &S);
/// \brief Inform the semantic consumer that Sema is no longer available.
virtual void ForgetSema();
/// \brief Load the contents of the global method pool for a given
/// selector.
virtual void ReadMethodPool(clang::Selector Sel);
virtual void ReadMethodPool(Selector Sel);
/// \brief Load the set of namespaces that are known to the external source,
/// which will be used during typo correction.
virtual void ReadKnownNamespaces(
clang::SmallVectorImpl<clang::NamespaceDecl*>& Namespaces);
virtual void ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces);
/// \brief Do last resort, unqualified lookup on a LookupResult that
/// Sema cannot find.
@ -74,7 +261,7 @@ public:
/// \param S the Scope of the identifier occurrence.
///
/// \return true to tell Sema to recover using the LookupResult.
virtual bool LookupUnqualified(clang::LookupResult& R, clang::Scope* S);
virtual bool LookupUnqualified(LookupResult &R, Scope *S);
/// \brief Read the set of tentative definitions known to the external Sema
/// source.
@ -83,8 +270,7 @@ public:
/// given vector of tentative definitions. Note that this routine may be
/// invoked multiple times; the external source should take care not to
/// introduce the same declarations repeatedly.
virtual void ReadTentativeDefinitions(
clang::SmallVectorImpl<clang::VarDecl*>& TentativeDefs);
virtual void ReadTentativeDefinitions(SmallVectorImpl<VarDecl*> &Defs);
/// \brief Read the set of unused file-scope declarations known to the
/// external Sema source.
@ -94,7 +280,7 @@ public:
/// invoked multiple times; the external source should take care not to
/// introduce the same declarations repeatedly.
virtual void ReadUnusedFileScopedDecls(
clang::SmallVectorImpl<const clang::DeclaratorDecl*>& Decls);
SmallVectorImpl<const DeclaratorDecl*> &Decls);
/// \brief Read the set of delegating constructors known to the
/// external Sema source.
@ -104,7 +290,7 @@ public:
/// invoked multiple times; the external source should take care not to
/// introduce the same declarations repeatedly.
virtual void ReadDelegatingConstructors(
clang::SmallVectorImpl<clang::CXXConstructorDecl*>& Decls);
SmallVectorImpl<CXXConstructorDecl*> &Decls);
/// \brief Read the set of ext_vector type declarations known to the
/// external Sema source.
@ -113,8 +299,7 @@ public:
/// the given vector of declarations. Note that this routine may be
/// invoked multiple times; the external source should take care not to
/// introduce the same declarations repeatedly.
virtual void ReadExtVectorDecls(
clang::SmallVectorImpl<clang::TypedefNameDecl*>& Decls);
virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl*> &Decls);
/// \brief Read the set of dynamic classes known to the external Sema source.
///
@ -122,8 +307,7 @@ public:
/// the given vector of declarations. Note that this routine may be
/// invoked multiple times; the external source should take care not to
/// introduce the same declarations repeatedly.
virtual void ReadDynamicClasses(
clang::SmallVectorImpl<clang::CXXRecordDecl*>& Decls);
virtual void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl*> &Decls);
/// \brief Read the set of locally-scoped external declarations known to the
/// external Sema source.
@ -132,8 +316,7 @@ public:
/// declarations to the given vector of declarations. Note that this routine
/// may be invoked multiple times; the external source should take care not
/// to introduce the same declarations repeatedly.
virtual void ReadLocallyScopedExternalDecls(
clang::SmallVectorImpl<clang::NamedDecl*>& Decls);
virtual void ReadLocallyScopedExternalDecls(SmallVectorImpl<NamedDecl*>&Decls);
/// \brief Read the set of referenced selectors known to the
/// external Sema source.
@ -142,9 +325,8 @@ public:
/// given vector of selectors. Note that this routine
/// may be invoked multiple times; the external source should take care not
/// to introduce the same selectors repeatedly.
virtual void ReadReferencedSelectors(
clang::SmallVectorImpl<std::pair<clang::Selector,
clang::SourceLocation> >& Sels);
virtual void ReadReferencedSelectors(SmallVectorImpl<std::pair<Selector,
SourceLocation> > &Sels);
/// \brief Read the set of weak, undeclared identifiers known to the
/// external Sema source.
@ -154,15 +336,14 @@ public:
/// the external source should take care not to introduce the same identifiers
/// repeatedly.
virtual void ReadWeakUndeclaredIdentifiers(
clang::SmallVectorImpl<std::pair<clang::IdentifierInfo*,
clang::WeakInfo> >& WI);
SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> > &WI);
/// \brief Read the set of used vtables known to the external Sema source.
///
/// The external source should append its own used vtables to the given
/// vector. Note that this routine may be invoked multiple times; the external
/// source should take care not to introduce the same vtables repeatedly.
virtual void ReadUsedVTables(clang::SmallVectorImpl<clang::ExternalVTableUse>& VTables);
virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables);
/// \brief Read the set of pending instantiations known to the external
/// Sema source.
@ -172,13 +353,13 @@ public:
/// external source should take care not to introduce the same instantiations
/// repeatedly.
virtual void ReadPendingInstantiations(
clang::SmallVectorImpl<std::pair<clang::ValueDecl*,
clang::SourceLocation> >& Pending);
SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending);
// isa/cast/dyn_cast support
static bool classof(const MultiplexExternalSemaSource*) { return true; }
//static bool classof(const ExternalSemaSource*) { return true; }
};
} // end namespace cling
} // end namespace clang
#endif // CLING_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H
#endif // LLVM_CLANG_SEMA_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H

View File

@ -81,7 +81,7 @@ namespace cling {
///
NestedTransactions m_NestedTransactions;
unsigned m_State : 2;
unsigned m_State : 3;
unsigned m_IssuedDiags : 2;
@ -119,6 +119,7 @@ namespace cling {
kUnknown,
kRolledBack,
kRolledBackWithErrors,
kCommitting,
kCommitted
};
@ -143,6 +144,7 @@ namespace cling {
typedef NestedTransactions::const_iterator const_nested_iterator;
typedef NestedTransactions::const_reverse_iterator const_reverse_nested_iterator;
// FIXME: misnomer, doesn't iterate over decls!
const_nested_iterator nested_decls_begin() const {
return m_NestedTransactions.begin();
}
@ -235,6 +237,14 @@ namespace cling {
m_NestedTransactions.push_back(nested);
}
///\brief Direct access.
///
const DelayCallInfo& operator[](size_t I) const { return m_DeclQueue[I]; }
///\brief Direct access, non-const.
///
DelayCallInfo& operator[](size_t I) { return m_DeclQueue[I]; }
///\brief Returns the declaration count.
///
size_t size() const { return m_DeclQueue.size(); }

View File

@ -24,11 +24,14 @@ namespace cling {
if (!getTransaction()->getCompilationOpts().Debug)
return;
for (Transaction::const_iterator I = getTransaction()->decls_begin(),
E = getTransaction()->decls_end(); I != E; ++I)
for (DeclGroupRef::const_iterator J = (*I).m_DGR.begin(),
JE = (*I).m_DGR.end(); J != JE; ++J)
// FIXME: Size might change in the loop!
for (size_t Idx = 0; Idx < getTransaction()->size(); ++Idx) {
// Copy DCI; it might get relocated below.
Transaction::DelayCallInfo I = (*getTransaction())[Idx];
for (DeclGroupRef::const_iterator J = I.m_DGR.begin(),
JE = I.m_DGR.end(); J != JE; ++J)
printDecl(*J);
}
}
void ASTDumper::printDecl(Decl* D) {

View File

@ -84,11 +84,13 @@ namespace cling {
// if (!getTransaction()->getCompilationOpts().ResultEvaluation)
// return;
AutoFixer autoFixer(m_Sema);
for (Transaction::const_iterator I = getTransaction()->decls_begin(),
E = getTransaction()->decls_end(); I != E; ++I)
for (DeclGroupRef::const_iterator J = (*I).m_DGR.begin(),
JE = (*I).m_DGR.end(); J != JE; ++J)
// size can change in the loop!
for (size_t Idx = 0; Idx < getTransaction()->size(); ++Idx) {
Transaction::DelayCallInfo I = (*getTransaction())[Idx];
for (DeclGroupRef::const_iterator J = I.m_DGR.begin(),
JE = I.m_DGR.end(); J != JE; ++J)
if ((*J)->hasBody())
autoFixer.Fix(cast<CompoundStmt>((*J)->getBody()));
}
}
} // end namespace cling

View File

@ -205,6 +205,7 @@ namespace cling {
return 0;
}
}
CI->setTarget(TargetInfo::CreateTargetInfo(CI->getDiagnostics(),
Invocation->getTargetOpts()));
if (!CI->hasTarget()) {
@ -212,6 +213,7 @@ namespace cling {
CI = 0;
return 0;
}
CI->getTarget().setForcedLangOptions(CI->getLangOpts());
SetClingTargetLangOpts(CI->getLangOpts(), CI->getTarget());
if (CI->getTarget().getTriple().getOS() == llvm::Triple::Cygwin) {
@ -234,6 +236,28 @@ namespace cling {
// Set up the memory buffer
if (buffer)
CI->getSourceManager().createMainFileIDForMemBuffer(buffer);
else {
// As main file we want
// * a virtual file that is claiming to be huge
// * with an empty memory buffer attached (to bring the content)
SourceManager& SM = CI->getSourceManager();
FileManager& FM = SM.getFileManager();
// Build the virtual file
const char* Filename = "InteractiveInputLineIncluder.h";
const std::string& CGOptsMainFileName
= CI->getInvocation().getCodeGenOpts().MainFileName;
if (!CGOptsMainFileName.empty())
Filename = CGOptsMainFileName.c_str();
const FileEntry* FE
= FM.getVirtualFile(Filename, 1U << 15U, time(0));
FileID MainFileID = SM.createMainFileID(FE, SrcMgr::C_User);
const SrcMgr::SLocEntry& MainFileSLocE = SM.getSLocEntry(MainFileID);
const SrcMgr::ContentCache* MainFileCC
= MainFileSLocE.getFile().getContentCache();
llvm::MemoryBuffer* MainFileMB
= llvm::MemoryBuffer::getMemBuffer("/*CLING MAIN FILE*/\n");
const_cast<SrcMgr::ContentCache*>(MainFileCC)->setBuffer(MainFileMB);
}
// Set up the preprocessor
CI->createPreprocessor();
@ -265,11 +289,12 @@ namespace cling {
// the JIT to crash
// When asserts are on, TURN ON not compare the VerifyModule
assert(CI->getCodeGenOpts().VerifyModule = 1);
return CI;
}
void CIFactory::SetClingCustomLangOpts(LangOptions& Opts) {
Opts.EmitAllDecls = 1;
Opts.EmitAllDecls = 0;
Opts.Exceptions = 1;
Opts.CXXExceptions = 1;
Opts.Deprecated = 1;

View File

@ -216,10 +216,12 @@ namespace cling {
Initialize();
}
for (Transaction::const_iterator I = getTransaction()->decls_begin(),
E = getTransaction()->decls_end(); I != E; ++I)
for (DeclGroupRef::const_iterator J = (*I).m_DGR.begin(),
JE = (*I).m_DGR.end(); J != JE; ++J)
// size can change in the loop!
for (size_t Idx = 0; Idx < getTransaction()->size(); ++Idx) {
// Copy DCI, might get reallocated below.
Transaction::DelayCallInfo I = (*getTransaction())[Idx];
for (DeclGroupRef::const_iterator J = I.m_DGR.begin(),
JE = I.m_DGR.end(); J != JE; ++J)
if (ShouldVisit(*J) && (*J)->hasBody()) {
if (FunctionDecl* FD = dyn_cast<FunctionDecl>(*J)) {
// Set the decl context, which is needed by Evaluate.
@ -230,6 +232,7 @@ namespace cling {
assert ((!isa<BlockDecl>(*J) || !isa<ObjCMethodDecl>(*J))
&& "Not implemented yet!");
}
}
//TODO: Check for error before returning.
}

View File

@ -23,6 +23,7 @@
#include "clang/AST/DeclGroup.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/FileManager.h"
#include "clang/CodeGen/CodeGenModule.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Parse/Parser.h"
#include "clang/Lex/Preprocessor.h"
@ -50,7 +51,7 @@ namespace cling {
m_LastTransaction(0) {
CompilerInstance* CI
= CIFactory::createCI(llvm::MemoryBuffer::getMemBuffer("", "CLING"),
= CIFactory::createCI(0 /*llvm::MemoryBuffer::getMemBuffer("", "CLING")*/,
argc, argv, llvmdir);
assert(CI && "CompilerInstance is (null)!");
@ -77,16 +78,40 @@ namespace cling {
m_TTransformers.push_back(new ReturnSynthesizer(TheSema));
m_TTransformers.push_back(new ASTDumper());
m_TTransformers.push_back(new DeclExtractor(TheSema));
}
void IncrementalParser::Initialize() {
// pull in PCHs
if (getCodeGenerator())
getCodeGenerator()->Initialize(getCI()->getASTContext());
const std::string& PCHFileName
= m_CI->getInvocation ().getPreprocessorOpts().ImplicitPCHInclude;
if (!PCHFileName.empty()) {
CompilationOptions CO;
CO.DeclarationExtraction = 0;
CO.ValuePrinting = CompilationOptions::VPDisabled;
CO.CodeGeneration = hasCodeGenerator();
beginTransaction(CO);
m_CI->createPCHExternalASTSource(PCHFileName,
true /*DisablePCHValidation*/,
true /*DisableStatCache*/,
true /*AllowPCHWithCompilerErrors*/,
0 /*DeserializationListener*/);
commitTransaction(endTransaction());
}
m_Parser.reset(new Parser(CI->getPreprocessor(), *TheSema,
Sema* TheSema = &m_CI->getSema();
m_Parser.reset(new Parser(m_CI->getPreprocessor(), *TheSema,
false /*skipFuncBodies*/));
CI->getPreprocessor().EnterMainSourceFile();
m_CI->getPreprocessor().EnterMainSourceFile();
// Initialize the parser after we have entered the main source file.
m_Parser->Initialize();
// Perform initialization that occurs after the parser has been initialized
// but before it parses anything. Initializes the consumers too.
CI->getSema().Initialize();
TheSema->Initialize();
ExternalASTSource *External = TheSema->getASTContext().getExternalSource();
if (External)
External->StartTranslationUnit(m_Consumer);
}
IncrementalParser::~IncrementalParser() {
@ -179,6 +204,8 @@ namespace cling {
//Transaction* CurT = m_Consumer->getTransaction();
assert(T->isCompleted() && "Transaction not ended!?");
T->setState(Transaction::kCommitting);
// Check for errors...
if (T->getIssuedDiags() == Transaction::kErrors) {
rollbackTransaction(T);
@ -215,7 +242,8 @@ namespace cling {
if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) {
// Reset the module builder to clean up global initializers, c'tors, d'tors
getCodeGenerator()->Initialize(getCI()->getASTContext());
CodeGen::CodeGenModule* CGM = getCodeGenerator()->GetBuilder();
CGM->Release();
// codegen the transaction
if (T->getCompilationOpts().CodeGenerationForModule) {
@ -233,11 +261,13 @@ namespace cling {
llvm::SmallVector<FunctionDecl*, 32> inlines;
InlineCollector IC(inlines);
for (Transaction::iterator I = T->decls_begin(), E = T->decls_end();
I != E; ++I) {
if (I->m_Call == Transaction::kCCIHandleTopLevelDecl)
for (DeclGroupRef::const_iterator J = (*I).m_DGR.begin(),
JE = (*I).m_DGR.end(); J != JE; ++J) {
// FIXME: Size might change in the loop!
for (size_t Idx = 0; Idx < T->size(); ++Idx) {
// Copy DCI; it might get relocated below.
Transaction::DelayCallInfo I = (*T)[Idx];
if (I.m_Call == Transaction::kCCIHandleTopLevelDecl)
for (DeclGroupRef::const_iterator J = I.m_DGR.begin(),
JE = I.m_DGR.end(); J != JE; ++J) {
// Traverse the TagDecl to find the inlined members.
inlines.clear();
@ -249,33 +279,38 @@ namespace cling {
}
}
}
} else for (Transaction::iterator I = T->decls_begin(), E = T->decls_end();
I != E; ++I) {
if (I->m_Call == Transaction::kCCIHandleTopLevelDecl)
getCodeGenerator()->HandleTopLevelDecl(I->m_DGR);
else if (I->m_Call == Transaction::kCCIHandleInterestingDecl)
getCodeGenerator()->HandleInterestingDecl(I->m_DGR);
else if(I->m_Call == Transaction::kCCIHandleTagDeclDefinition) {
TagDecl* TD = cast<TagDecl>(I->m_DGR.getSingleDecl());
} else for (size_t Idx = 0; Idx < T->size() /*can change in the loop!*/;
++Idx) {
// Copy DCI; it might get relocated below.
Transaction::DelayCallInfo I = (*T)[Idx];
if (I.m_Call == Transaction::kCCIHandleTopLevelDecl)
getCodeGenerator()->HandleTopLevelDecl(I.m_DGR);
else if (I.m_Call == Transaction::kCCIHandleInterestingDecl) {
// Usually through BackendConsumer which doesn't implement
// HandleInterestingDecl() and thus calls
// ASTConsumer::HandleInterestingDecl()
getCodeGenerator()->HandleTopLevelDecl(I.m_DGR);
} else if(I.m_Call == Transaction::kCCIHandleTagDeclDefinition) {
TagDecl* TD = cast<TagDecl>(I.m_DGR.getSingleDecl());
getCodeGenerator()->HandleTagDeclDefinition(TD);
}
else if (I->m_Call == Transaction::kCCIHandleVTable) {
CXXRecordDecl* CXXRD = cast<CXXRecordDecl>(I->m_DGR.getSingleDecl());
else if (I.m_Call == Transaction::kCCIHandleVTable) {
CXXRecordDecl* CXXRD = cast<CXXRecordDecl>(I.m_DGR.getSingleDecl());
getCodeGenerator()->HandleVTable(CXXRD, /*isRequired*/true);
}
else if (I->m_Call
else if (I.m_Call
== Transaction::kCCIHandleCXXImplicitFunctionInstantiation) {
FunctionDecl* FD = cast<FunctionDecl>(I->m_DGR.getSingleDecl());
FunctionDecl* FD = cast<FunctionDecl>(I.m_DGR.getSingleDecl());
getCodeGenerator()->HandleCXXImplicitFunctionInstantiation(FD);
}
else if (I->m_Call
else if (I.m_Call
== Transaction::kCCIHandleCXXStaticMemberVarInstantiation) {
VarDecl* VD = cast<VarDecl>(I->m_DGR.getSingleDecl());
VarDecl* VD = cast<VarDecl>(I.m_DGR.getSingleDecl());
getCodeGenerator()->HandleCXXStaticMemberVarInstantiation(VD);
}
else if (I->m_Call == Transaction::kCCINone)
else if (I.m_Call == Transaction::kCCINone)
; // We use that internally as delimiter in the Transaction.
else
llvm_unreachable("We shouldn't have decl without call info.");
@ -290,11 +325,23 @@ namespace cling {
}
}
T->setState(Transaction::kCommitted);
InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks();
if (callbacks)
if (callbacks) {
callbacks->TransactionCommitted(*T);
if (T->hasNestedTransactions()) {
Transaction* SubTransactionWhileCommitting = *T->rnested_decls_begin();
if (SubTransactionWhileCommitting->getState()
== Transaction::kUnknown) {
// A nested transaction was created while committing this
// transaction; commit it now.
SubTransactionWhileCommitting->setCompleted();
commitTransaction(SubTransactionWhileCommitting);
}
}
}
T->setState(Transaction::kCommitted);
}
void IncrementalParser::rollbackTransaction(Transaction* T) const {
@ -348,11 +395,13 @@ namespace cling {
//
void IncrementalParser::CreateSLocOffsetGenerator() {
SourceManager& SM = getCI()->getSourceManager();
#if 0
FileManager& FM = SM.getFileManager();
const FileEntry* FE
= FM.getVirtualFile("InteractiveInputLineIncluder.h", 1U << 15U, time(0));
m_VirtualFileID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
#endif
m_VirtualFileID = SM.getMainFileID();
assert(!m_VirtualFileID.isInvalid() && "No VirtualFileID created?");
}

View File

@ -97,6 +97,7 @@ namespace cling {
const char* llvmdir);
~IncrementalParser();
void Initialize();
clang::CompilerInstance* getCI() const { return m_CI.get(); }
clang::Parser* getParser() const { return m_Parser.get(); }
clang::CodeGenerator* getCodeGenerator() const { return m_CodeGen.get(); }

View File

@ -144,6 +144,8 @@ namespace cling {
m_ExecutionContext.reset(new ExecutionContext());
m_IncrParser->Initialize();
// Add path to interpreter's include files
// Try to find the headers in the src folder first
#ifdef CLING_SRCDIR_INCL
@ -196,12 +198,19 @@ namespace cling {
declare("#include \"cling/Interpreter/RuntimeUniverse.h\"");
declare("#include \"cling/Interpreter/ValuePrinter.h\"");
// Set up the gCling variable
std::stringstream initializer;
initializer << "namespace cling {namespace runtime { "
"cling::Interpreter *gCling=(cling::Interpreter*)"
<< (uintptr_t)this << ";} }";
declare(initializer.str());
if (getCodeGenerator()) {
// Set up the gCling variable if it can be used
std::stringstream initializer;
initializer << "namespace cling {namespace runtime { "
"cling::Interpreter *gCling=(cling::Interpreter*)"
<< (uintptr_t)this << ";} }";
declare(initializer.str());
#if 0
initializer << "cling::runtime::gCling=(cling::Interpreter*)"
<< (uintptr_t)this << ";";
execute(initializer.str());
#endif
}
}
else {
declare("#include \"cling/Interpreter/CValuePrinter.h\"");

View File

@ -1,112 +1,270 @@
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author: Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------
#include "cling/Interpreter/MultiplexExternalSemaSource.h"
//===--- MultiplexExternalSemaSource.cpp ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the event dispatching to the subscribed clients.
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/Sema/Lookup.h"
using namespace clang;
namespace cling {
MultiplexExternalSemaSource::MultiplexExternalSemaSource(
llvm::ArrayRef<ExternalSemaSource*> sources) {
for (size_t i = 0; i < sources.size(); ++i)
m_Sources.push_back(sources[i]);
///\brief Constructs a new multiplexing external sema source and appends the
/// given element to it.
///
///\param[in] source - An ExternalSemaSource.
///
MultiplexExternalSemaSource::MultiplexExternalSemaSource(ExternalSemaSource &s1,
ExternalSemaSource &s2){
Sources.push_back(&s1);
Sources.push_back(&s2);
}
// pin the vtable here.
MultiplexExternalSemaSource::~MultiplexExternalSemaSource() {}
///\brief Appends new source to the source list.
///
///\param[in] source - An ExternalSemaSource.
///
void MultiplexExternalSemaSource::addSource(ExternalSemaSource &source) {
Sources.push_back(&source);
}
//===----------------------------------------------------------------------===//
// ExternalASTSource.
//===----------------------------------------------------------------------===//
Decl *MultiplexExternalSemaSource::GetExternalDecl(uint32_t ID) {
for(size_t i = 0; i < Sources.size(); ++i)
if (Decl *Result = Sources[i]->GetExternalDecl(ID))
return Result;
return 0;
}
Selector MultiplexExternalSemaSource::GetExternalSelector(uint32_t ID) {
Selector Sel;
for(size_t i = 0; i < Sources.size(); ++i) {
Sel = Sources[i]->GetExternalSelector(ID);
if (!Sel.isNull())
return Sel;
}
return Sel;
}
uint32_t MultiplexExternalSemaSource::GetNumExternalSelectors() {
uint32_t total = 0;
for(size_t i = 0; i < Sources.size(); ++i)
total += Sources[i]->GetNumExternalSelectors();
return total;
}
// pin the vtable here.
MultiplexExternalSemaSource::~MultiplexExternalSemaSource() {}
Stmt *MultiplexExternalSemaSource::GetExternalDeclStmt(uint64_t Offset) {
for(size_t i = 0; i < Sources.size(); ++i)
if (Stmt *Result = Sources[i]->GetExternalDeclStmt(Offset))
return Result;
return 0;
}
void MultiplexExternalSemaSource::InitializeSema(Sema& S) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->InitializeSema(S);
CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers(
uint64_t Offset){
for(size_t i = 0; i < Sources.size(); ++i)
if (CXXBaseSpecifier *R = Sources[i]->GetExternalCXXBaseSpecifiers(Offset))
return R;
return 0;
}
DeclContextLookupResult MultiplexExternalSemaSource::
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) {
StoredDeclsList DeclsFound;
for(size_t i = 0; i < Sources.size(); ++i) {
DeclContext::lookup_result R =
Sources[i]->FindExternalVisibleDeclsByName(DC, Name);
for (DeclContext::lookup_iterator I = R.first, E = R.second; I != E;
++I) {
if (!DeclsFound.HandleRedeclaration(*I))
DeclsFound.AddSubsequentDecl(*I);
}
}
return DeclsFound.getLookupResult();
}
void MultiplexExternalSemaSource::ForgetSema() {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ForgetSema();
}
void MultiplexExternalSemaSource::completeVisibleDeclsMap(const DeclContext *DC){
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->completeVisibleDeclsMap(DC);
}
void MultiplexExternalSemaSource::ReadMethodPool(Selector Sel) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadMethodPool(Sel);
}
ExternalLoadResult MultiplexExternalSemaSource::
FindExternalLexicalDecls(const DeclContext *DC,
bool (*isKindWeWant)(Decl::Kind),
SmallVectorImpl<Decl*> &Result) {
for(size_t i = 0; i < Sources.size(); ++i)
// FIXME: The semantics of the return result is unclear to me...
Sources[i]->FindExternalLexicalDecls(DC, isKindWeWant, Result);
void MultiplexExternalSemaSource::ReadKnownNamespaces(
SmallVectorImpl<NamespaceDecl*>& Namespaces){
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadKnownNamespaces(Namespaces);
}
return ELR_Success;
}
void MultiplexExternalSemaSource::FindFileRegionDecls(FileID File,
unsigned Offset,
unsigned Length,
SmallVectorImpl<Decl *> &Decls){
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->FindFileRegionDecls(File, Offset, Length, Decls);
}
void MultiplexExternalSemaSource::CompleteType(TagDecl *Tag) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->CompleteType(Tag);
}
void MultiplexExternalSemaSource::CompleteType(ObjCInterfaceDecl *Class) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->CompleteType(Class);
}
void MultiplexExternalSemaSource::ReadComments() {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadComments();
}
void MultiplexExternalSemaSource::StartedDeserializing() {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->StartedDeserializing();
}
void MultiplexExternalSemaSource::FinishedDeserializing() {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->FinishedDeserializing();
}
void MultiplexExternalSemaSource::StartTranslationUnit(ASTConsumer *Consumer) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->StartTranslationUnit(Consumer);
}
void MultiplexExternalSemaSource::PrintStats() {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->PrintStats();
}
bool MultiplexExternalSemaSource::layoutRecordType(const RecordDecl *Record,
uint64_t &Size,
uint64_t &Alignment,
llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets){
for(size_t i = 0; i < Sources.size(); ++i)
if (Sources[i]->layoutRecordType(Record, Size, Alignment, FieldOffsets,
BaseOffsets, VirtualBaseOffsets))
return true;
return false;
}
void MultiplexExternalSemaSource::
getMemoryBufferSizes(MemoryBufferSizes &sizes) const {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->getMemoryBufferSizes(sizes);
}
//===----------------------------------------------------------------------===//
// ExternalSemaSource.
//===----------------------------------------------------------------------===//
void MultiplexExternalSemaSource::InitializeSema(Sema &S) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->InitializeSema(S);
}
void MultiplexExternalSemaSource::ForgetSema() {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ForgetSema();
}
void MultiplexExternalSemaSource::ReadMethodPool(Selector Sel) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadMethodPool(Sel);
}
void MultiplexExternalSemaSource::ReadKnownNamespaces(
SmallVectorImpl<NamespaceDecl*> &Namespaces){
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadKnownNamespaces(Namespaces);
}
bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult& R, Scope* S){
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->LookupUnqualified(R, S);
return !R.empty();
}
void MultiplexExternalSemaSource::ReadTentativeDefinitions(
SmallVectorImpl<VarDecl*>& TentativeDefs) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadTentativeDefinitions(TentativeDefs);
}
bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->LookupUnqualified(R, S);
void MultiplexExternalSemaSource::ReadUnusedFileScopedDecls(
SmallVectorImpl<const DeclaratorDecl*>& Decls) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadUnusedFileScopedDecls(Decls);
}
return !R.empty();
}
void MultiplexExternalSemaSource::ReadTentativeDefinitions(
SmallVectorImpl<VarDecl*> &TentativeDefs) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadTentativeDefinitions(TentativeDefs);
}
void MultiplexExternalSemaSource::ReadDelegatingConstructors(
SmallVectorImpl<CXXConstructorDecl*>& Decls) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadDelegatingConstructors(Decls);
}
void MultiplexExternalSemaSource::ReadUnusedFileScopedDecls(
SmallVectorImpl<const DeclaratorDecl*> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadUnusedFileScopedDecls(Decls);
}
void MultiplexExternalSemaSource::ReadDelegatingConstructors(
SmallVectorImpl<CXXConstructorDecl*> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadDelegatingConstructors(Decls);
}
void MultiplexExternalSemaSource::ReadExtVectorDecls(
SmallVectorImpl<TypedefNameDecl*>& Decls) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadExtVectorDecls(Decls);
}
void MultiplexExternalSemaSource::ReadExtVectorDecls(
SmallVectorImpl<TypedefNameDecl*> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadExtVectorDecls(Decls);
}
void MultiplexExternalSemaSource::ReadDynamicClasses(
SmallVectorImpl<CXXRecordDecl*>& Decls) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadDynamicClasses(Decls);
}
void MultiplexExternalSemaSource::ReadDynamicClasses(
SmallVectorImpl<CXXRecordDecl*> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadDynamicClasses(Decls);
}
void MultiplexExternalSemaSource::ReadLocallyScopedExternalDecls(
SmallVectorImpl<NamedDecl*>& Decls) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadLocallyScopedExternalDecls(Decls);
}
void MultiplexExternalSemaSource::ReadLocallyScopedExternalDecls(
SmallVectorImpl<NamedDecl*> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadLocallyScopedExternalDecls(Decls);
}
void MultiplexExternalSemaSource::ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation> >& Sels) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadReferencedSelectors(Sels);
}
void MultiplexExternalSemaSource::ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadReferencedSelectors(Sels);
}
void MultiplexExternalSemaSource::ReadWeakUndeclaredIdentifiers(
SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> >& WI) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadWeakUndeclaredIdentifiers(WI);
}
void MultiplexExternalSemaSource::ReadWeakUndeclaredIdentifiers(
SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> > &WI) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadWeakUndeclaredIdentifiers(WI);
}
void MultiplexExternalSemaSource::ReadUsedVTables(
SmallVectorImpl<ExternalVTableUse>& VTables) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadUsedVTables(VTables);
}
void MultiplexExternalSemaSource::ReadUsedVTables(
SmallVectorImpl<ExternalVTableUse> &VTables) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadUsedVTables(VTables);
}
void MultiplexExternalSemaSource::ReadPendingInstantiations(
void MultiplexExternalSemaSource::ReadPendingInstantiations(
SmallVectorImpl<std::pair<ValueDecl*,
SourceLocation> >& Pending) {
for(size_t i = 0; i < m_Sources.size(); ++i)
m_Sources[i]->ReadPendingInstantiations(Pending);
}
} // end namespace cling
SourceLocation> > &Pending) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadPendingInstantiations(Pending);
}

View File

@ -27,6 +27,30 @@ namespace cling {
// return;
// }
// register the wrapper if any.
if (getState() == kCommitting) {
// We are committing and getting enw decls in.
// Move them into a sub transaction that will be processed
// recursively at the end of of commitTransaction.
Transaction* subTransactionWhileCommitting = 0;
if (hasNestedTransactions()
&& m_NestedTransactions.back()->getState() == kUnknown)
subTransactionWhileCommitting = m_NestedTransactions.back();
else {
// FIXME: is this correct (Axel says "yes")
CompilationOptions Opts(getCompilationOpts());
Opts.DeclarationExtraction = 0;
Opts.ValuePrinting = CompilationOptions::VPDisabled;
Opts.ResultEvaluation = 0;
Opts.DynamicScoping = 0;
subTransactionWhileCommitting
= new Transaction(Opts, getModule());
addNestedTransaction(subTransactionWhileCommitting);
}
subTransactionWhileCommitting->append(DCI);
return;
}
if (DCI.m_DGR.isSingleDecl()) {
if (FunctionDecl* FD = dyn_cast<FunctionDecl>(DCI.m_DGR.getSingleDecl()))
if (utils::Analyze::IsWrapper(FD)) {