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