From d670325ee1a95e0bd138ab7fad4ef6a2c40e69ef Mon Sep 17 00:00:00 2001 From: Raphael Isemann <teemperor@gmail.com> Date: Thu, 14 Sep 2017 15:14:49 +0200 Subject: [PATCH] [cxxmodules] Don't overrite the DeserializationListener. With the module generation in rootcling Clang rlies on AST consumers to do the module generation work for it. Right now this doesn't work however with the interpreter, as we just overwrite the deserialization listener that clang added which will cause strange errors during the module generation (the most prompinent error is that the number of recorded submodules will be incorrect, as this it the first thing that Clang checks before writing a module and which is recorded by an ASTDeserializationListener). This patch just adds a multiplexer here that allows us to keep the old listener while also adding the one we have. --- .../lib/Interpreter/InterpreterCallbacks.cpp | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/interpreter/cling/lib/Interpreter/InterpreterCallbacks.cpp b/interpreter/cling/lib/Interpreter/InterpreterCallbacks.cpp index 093fd4da286..6768192c74a 100644 --- a/interpreter/cling/lib/Interpreter/InterpreterCallbacks.cpp +++ b/interpreter/cling/lib/Interpreter/InterpreterCallbacks.cpp @@ -12,12 +12,13 @@ #include "cling/Interpreter/Interpreter.h" #include "clang/AST/ASTContext.h" -#include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/MultiplexConsumer.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/Sema.h" -#include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTDeserializationListener.h" +#include "clang/Serialization/ASTReader.h" using namespace clang; @@ -78,6 +79,19 @@ namespace cling { } }; + /// \brief Wraps an ASTDeserializationListener in an ASTConsumer so that + /// it can be used with a MultiplexConsumer. + class DeserializationListenerWrapper : public ASTConsumer { + ASTDeserializationListener* m_Listener; + + public: + DeserializationListenerWrapper(ASTDeserializationListener* Listener) + : m_Listener(Listener) {} + ASTDeserializationListener* GetASTDeserializationListener() override { + return m_Listener; + } + }; + ///\brief Translates 'interesting' for the interpreter ExternalSemaSource /// events into interpreter callbacks. /// @@ -187,11 +201,24 @@ namespace cling { } if (enableDeserializationListenerCallbacks && Reader) { - // FIXME: need to create a multiplexer if a DeserializationListener is - // alreday present. + // Create a new deserialization listener. m_DeserializationListener. reset(new InterpreterDeserializationListener(this)); - Reader->setDeserializationListener(m_DeserializationListener.get()); + + // Wrap the deserialization listener in an MultiplexConsumer and then + // combine it with the existing Consumer. + // FIXME: Maybe it's better to make MultiplexASTDeserializationListener + // public instead. See also: https://reviews.llvm.org/D37475 + std::unique_ptr<DeserializationListenerWrapper> wrapper( + new DeserializationListenerWrapper(m_DeserializationListener.get())); + + std::vector<std::unique_ptr<ASTConsumer>> Consumers; + Consumers.push_back(std::move(wrapper)); + Consumers.push_back(std::move(m_Interpreter->getCI()->takeASTConsumer())); + + std::unique_ptr<clang::MultiplexConsumer> multiConsumer( + new clang::MultiplexConsumer(std::move(Consumers))); + m_Interpreter->getCI()->setASTConsumer(std::move(multiConsumer)); } if (enablePPCallbacks) { -- GitLab