Multiplex the ExternalASTSource in cling
We need to respect the existing ExternalASTSource when setting up the interpreter. Otherwise the ASTReader (which is the existing source) doesn't receive the required callbacks to properly load C++ modules. This patch now creates a multiplexer that contains our new ASTSource and the existing one if it's necessary. We also no longer attach the existing sema source which seemingly was only a workaround that only works for the special case were the external sema source and the external AST source are the same object.
This commit is contained in:
parent
62eac4d1d2
commit
c41a49dabb
@ -16,6 +16,7 @@
|
|||||||
#include "clang/Frontend/MultiplexConsumer.h"
|
#include "clang/Frontend/MultiplexConsumer.h"
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include "clang/Lex/Preprocessor.h"
|
||||||
#include "clang/Sema/CodeCompleteConsumer.h"
|
#include "clang/Sema/CodeCompleteConsumer.h"
|
||||||
|
#include "clang/Sema/MultiplexExternalSemaSource.h"
|
||||||
#include "clang/Sema/Sema.h"
|
#include "clang/Sema/Sema.h"
|
||||||
#include "clang/Serialization/ASTDeserializationListener.h"
|
#include "clang/Serialization/ASTDeserializationListener.h"
|
||||||
#include "clang/Serialization/ASTReader.h"
|
#include "clang/Serialization/ASTReader.h"
|
||||||
@ -92,6 +93,120 @@ namespace cling {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief wraps an ExternalASTSource in an ExternalSemaSource. No functional
|
||||||
|
/// difference between the original source and this wrapper intended.
|
||||||
|
class ExternalASTSourceWrapper : public ExternalSemaSource {
|
||||||
|
ExternalASTSource* m_Source;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ExternalASTSourceWrapper(ExternalASTSource* Source) : m_Source(Source) {
|
||||||
|
assert(m_Source && "Can't wrap nullptr ExternalASTSource");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Decl* GetExternalDecl(uint32_t ID) override {
|
||||||
|
return m_Source->GetExternalDecl(ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Selector GetExternalSelector(uint32_t ID) override {
|
||||||
|
return m_Source->GetExternalSelector(ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint32_t GetNumExternalSelectors() override {
|
||||||
|
return m_Source->GetNumExternalSelectors();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Stmt* GetExternalDeclStmt(uint64_t Offset) override {
|
||||||
|
return m_Source->GetExternalDeclStmt(Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual CXXCtorInitializer**
|
||||||
|
GetExternalCXXCtorInitializers(uint64_t Offset) override {
|
||||||
|
return m_Source->GetExternalCXXCtorInitializers(Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual CXXBaseSpecifier*
|
||||||
|
GetExternalCXXBaseSpecifiers(uint64_t Offset) override {
|
||||||
|
return m_Source->GetExternalCXXBaseSpecifiers(Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void updateOutOfDateIdentifier(IdentifierInfo& II) override {
|
||||||
|
m_Source->updateOutOfDateIdentifier(II);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool FindExternalVisibleDeclsByName(const DeclContext* DC,
|
||||||
|
DeclarationName Name) override {
|
||||||
|
return m_Source->FindExternalVisibleDeclsByName(DC, Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void completeVisibleDeclsMap(const DeclContext* DC) override {
|
||||||
|
m_Source->completeVisibleDeclsMap(DC);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Module* getModule(unsigned ID) override {
|
||||||
|
return m_Source->getModule(ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual llvm::Optional<ASTSourceDescriptor>
|
||||||
|
getSourceDescriptor(unsigned ID) override {
|
||||||
|
return m_Source->getSourceDescriptor(ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ExtKind hasExternalDefinitions(const Decl* D) override {
|
||||||
|
return m_Source->hasExternalDefinitions(D);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
FindExternalLexicalDecls(const DeclContext* DC,
|
||||||
|
llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
|
||||||
|
SmallVectorImpl<Decl*>& Result) override {
|
||||||
|
m_Source->FindExternalLexicalDecls(DC, IsKindWeWant, Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void FindFileRegionDecls(FileID File, unsigned Offset,
|
||||||
|
unsigned Length,
|
||||||
|
SmallVectorImpl<Decl*>& Decls) override {
|
||||||
|
m_Source->FindFileRegionDecls(File, Offset, Length, Decls);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void CompleteRedeclChain(const Decl* D) override {
|
||||||
|
m_Source->CompleteRedeclChain(D);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void CompleteType(TagDecl* Tag) override {
|
||||||
|
m_Source->CompleteType(Tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void CompleteType(ObjCInterfaceDecl* Class) override {
|
||||||
|
m_Source->CompleteType(Class);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void ReadComments() override { m_Source->ReadComments(); }
|
||||||
|
|
||||||
|
virtual void StartedDeserializing() override {
|
||||||
|
m_Source->StartedDeserializing();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void FinishedDeserializing() override {
|
||||||
|
m_Source->FinishedDeserializing();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void StartTranslationUnit(ASTConsumer* Consumer) override {
|
||||||
|
m_Source->StartTranslationUnit(Consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void PrintStats() override { m_Source->PrintStats(); }
|
||||||
|
|
||||||
|
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)
|
||||||
|
override {
|
||||||
|
return m_Source->layoutRecordType(Record, Size, Alignment, FieldOffsets,
|
||||||
|
BaseOffsets, VirtualBaseOffsets);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
///\brief Translates 'interesting' for the interpreter ExternalSemaSource
|
///\brief Translates 'interesting' for the interpreter ExternalSemaSource
|
||||||
/// events into interpreter callbacks.
|
/// events into interpreter callbacks.
|
||||||
///
|
///
|
||||||
@ -187,14 +302,32 @@ namespace cling {
|
|||||||
m_ExternalSemaSource->InitializeSema(SemaRef);
|
m_ExternalSemaSource->InitializeSema(SemaRef);
|
||||||
m_Interpreter->getSema().addExternalSource(m_ExternalSemaSource);
|
m_Interpreter->getSema().addExternalSource(m_ExternalSemaSource);
|
||||||
|
|
||||||
// FIXME: We should add a multiplexer in the ASTContext, too.
|
// Overwrite the ExternalASTSource.
|
||||||
llvm::IntrusiveRefCntPtr<ExternalASTSource>
|
|
||||||
astContextExternalSource(SemaRef.getExternalSource());
|
|
||||||
clang::ASTContext& Ctx = SemaRef.getASTContext();
|
clang::ASTContext& Ctx = SemaRef.getASTContext();
|
||||||
// FIXME: This is a gross hack. We must make multiplexer in the
|
auto ExistingSource = Ctx.getExternalSource();
|
||||||
// astcontext or a derived class that extends what we need.
|
// If we already have source, we need to create a multiplexer with the
|
||||||
Ctx.ExternalSource.resetWithoutRelease();//FIXME: make sure we delete it.
|
// existing source.
|
||||||
Ctx.setExternalSource(astContextExternalSource);
|
if (ExistingSource) {
|
||||||
|
// Make sure the context is not deleting the existing source.
|
||||||
|
// FIXME: We should delete this, but looking at the other TODO's in
|
||||||
|
// the destructor we can't easily free our callbacks from here...
|
||||||
|
Ctx.ExternalSource.resetWithoutRelease();
|
||||||
|
|
||||||
|
// Wrap the existing source in a wrapper so that it becomes an
|
||||||
|
// external sema source. This way we can use the existing multiplexer
|
||||||
|
// for this.
|
||||||
|
auto wrapper = new ExternalASTSourceWrapper(ExistingSource);
|
||||||
|
|
||||||
|
// Wrap both the existing source and our source. We give our own
|
||||||
|
// source preference to the existing one.
|
||||||
|
IntrusiveRefCntPtr<ExternalASTSource> S;
|
||||||
|
S = new MultiplexExternalSemaSource(*m_ExternalSemaSource, *wrapper);
|
||||||
|
|
||||||
|
Ctx.setExternalSource(S);
|
||||||
|
} else {
|
||||||
|
// We don't have an existing source, so just set our own source.
|
||||||
|
Ctx.setExternalSource(m_ExternalSemaSource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableDeserializationListenerCallbacks && Reader) {
|
if (enableDeserializationListenerCallbacks && Reader) {
|
||||||
|
Loading…
Reference in New Issue
Block a user