[clang] [clang-repl] Implement value printing of custom types (PR #84769)

Vassil Vassilev via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 11 08:08:31 PDT 2024


https://github.com/vgvassilev created https://github.com/llvm/llvm-project/pull/84769

Differential revision: https://reviews.llvm.org/D146809

>From 05c3bb8b193552b4ed7dc2e22848623e07cc2715 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Sun, 16 Jul 2023 21:18:26 +0000
Subject: [PATCH 1/2] [clang-repl] Implement value printing of custom types.

Differential revision: https://reviews.llvm.org/D146809
---
 clang/include/clang/Interpreter/Interpreter.h |   6 +
 .../Interpreter/PartialTranslationUnit.h      |   2 +
 clang/include/clang/Interpreter/Value.h       |   7 +-
 clang/lib/Headers/CMakeLists.txt              |   1 +
 .../__clang_interpreter_runtime_printvalue.h  | 261 ++++++++
 clang/lib/Interpreter/CMakeLists.txt          |   1 +
 clang/lib/Interpreter/DeviceOffload.cpp       |   4 +-
 clang/lib/Interpreter/DeviceOffload.h         |   4 +-
 clang/lib/Interpreter/IncrementalExecutor.cpp |   8 +-
 clang/lib/Interpreter/IncrementalExecutor.h   |   7 +-
 clang/lib/Interpreter/IncrementalParser.cpp   |   5 +-
 clang/lib/Interpreter/IncrementalParser.h     |   5 +-
 clang/lib/Interpreter/Interpreter.cpp         |  29 +-
 clang/lib/Interpreter/InterpreterUtils.cpp    | 399 ++++++++++++-
 clang/lib/Interpreter/InterpreterUtils.h      |  22 +-
 clang/lib/Interpreter/Value.cpp               |  31 +-
 clang/lib/Interpreter/ValuePrinter.cpp        | 562 ++++++++++++++++++
 clang/test/Interpreter/pretty-print.cpp       | 206 +++++++
 clang/tools/clang-repl/CMakeLists.txt         |  59 ++
 clang/tools/clang-repl/ClangRepl.cpp          |  11 +-
 .../InterpreterExceptionTest.cpp              |   5 +-
 .../Interpreter/IncrementalProcessingTest.cpp |   5 +-
 .../unittests/Interpreter/InterpreterTest.cpp |   5 +-
 23 files changed, 1606 insertions(+), 39 deletions(-)
 create mode 100644 clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
 create mode 100644 clang/lib/Interpreter/ValuePrinter.cpp
 create mode 100644 clang/test/Interpreter/pretty-print.cpp

diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 292fa566ae7037..10ae4ce1de06bb 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -36,6 +36,8 @@ class ThreadSafeContext;
 namespace clang {
 
 class CompilerInstance;
+
+namespace caas {
 class IncrementalExecutor;
 class IncrementalParser;
 
@@ -105,6 +107,7 @@ class Interpreter {
   llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine();
 
   llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);
+  llvm::Error ExecuteModule(std::unique_ptr<llvm::Module> &M);
   llvm::Error Execute(PartialTranslationUnit &T);
   llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr);
   llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD);
@@ -137,6 +140,8 @@ class Interpreter {
 
   Expr *SynthesizeExpr(Expr *E);
 
+  std::unique_ptr<llvm::Module> GenModule();
+
 private:
   size_t getEffectivePTUSize() const;
 
@@ -146,6 +151,7 @@ class Interpreter {
 
   llvm::SmallVector<Expr *, 4> ValuePrintingInfo;
 };
+} // namespace caas
 } // namespace clang
 
 #endif // LLVM_CLANG_INTERPRETER_INTERPRETER_H
diff --git a/clang/include/clang/Interpreter/PartialTranslationUnit.h b/clang/include/clang/Interpreter/PartialTranslationUnit.h
index bf91d559452b8a..d28cd30010cb92 100644
--- a/clang/include/clang/Interpreter/PartialTranslationUnit.h
+++ b/clang/include/clang/Interpreter/PartialTranslationUnit.h
@@ -24,6 +24,7 @@ namespace clang {
 
 class TranslationUnitDecl;
 
+namespace caas {
 /// The class keeps track of various objects created as part of processing
 /// incremental inputs.
 struct PartialTranslationUnit {
@@ -32,6 +33,7 @@ struct PartialTranslationUnit {
   /// The llvm IR produced for the input.
   std::unique_ptr<llvm::Module> TheModule;
 };
+} // namespace caas
 } // namespace clang
 
 #endif // LLVM_CLANG_INTERPRETER_PARTIALTRANSLATIONUNIT_H
diff --git a/clang/include/clang/Interpreter/Value.h b/clang/include/clang/Interpreter/Value.h
index c380cd91550def..207e73307a1781 100644
--- a/clang/include/clang/Interpreter/Value.h
+++ b/clang/include/clang/Interpreter/Value.h
@@ -49,9 +49,11 @@ class raw_ostream;
 namespace clang {
 
 class ASTContext;
-class Interpreter;
 class QualType;
 
+namespace caas {
+class Interpreter;
+
 #if defined(_WIN32)
 // REPL_EXTERNAL_VISIBILITY are symbols that we need to be able to locate
 // at runtime. On Windows, this requires them to be exported from any of the
@@ -137,6 +139,7 @@ class REPL_EXTERNAL_VISIBILITY Value {
   void setOpaqueType(void *Ty) { OpaqueType = Ty; }
 
   void *getPtr() const;
+  void **getPtrAddress() const;
   void setPtr(void *Ptr) { Data.m_Ptr = Ptr; }
 
 #define X(type, name)                                                          \
@@ -203,6 +206,6 @@ template <> inline void *Value::as() const {
     return Data.m_Ptr;
   return (void *)as<uintptr_t>();
 }
-
+} // namespace caas
 } // namespace clang
 #endif
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index b9a966be73ee97..545e9fe98ee6fc 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -34,6 +34,7 @@ set(core_files
   tgmath.h
   unwind.h
   varargs.h
+  __clang_interpreter_runtime_printvalue.h
   )
 
 set(arm_common_files
diff --git a/clang/lib/Headers/__clang_interpreter_runtime_printvalue.h b/clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
new file mode 100644
index 00000000000000..707eb0723f092d
--- /dev/null
+++ b/clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
@@ -0,0 +1,261 @@
+//===--- __clang_interpreter_runtime_printvalue.h ---*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines runtime functions used to print STL components in
+// clang-repl. They are very heavy so we should only include it once and on
+// demand.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_INTERPRETER_RUNTIME_PRINT_VALUE_H
+#define LLVM_CLANG_INTERPRETER_RUNTIME_PRINT_VALUE_H
+
+#if !defined(__CLANG_REPL__)
+#error "This file should only be included by clang-repl!"
+#endif
+
+#include <memory>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <vector>
+
+// FIXME: We should include it somewhere instead of duplicating it...
+#if __has_attribute(visibility) &&                                             \
+    (!(defined(_WIN32) || defined(__CYGWIN__)) ||                              \
+     (defined(__MINGW32__) && defined(__clang__)))
+#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
+#define __REPL_EXTERNAL_VISIBILITY __attribute__((visibility("default")))
+#else
+#define __REPL_EXTERNAL_VISIBILITY
+#endif
+#else
+#if defined(_WIN32)
+#define __REPL_EXTERNAL_VISIBILITY __declspec(dllexport)
+#endif
+#endif
+
+// Fallback.
+template <class T,
+          typename std::enable_if<!std::is_pointer<T>::value>::type * = nullptr>
+inline std::string PrintValueRuntime(const T &) {
+  return "{not representable}";
+}
+
+#ifndef __DECL_PRINT_VALUE_RUNTIME
+#define __DECL_PRINT_VALUE_RUNTIME(type)                                       \
+  __REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const type *__Ptr)
+__DECL_PRINT_VALUE_RUNTIME(void);
+__DECL_PRINT_VALUE_RUNTIME(void *);
+__DECL_PRINT_VALUE_RUNTIME(bool);
+__DECL_PRINT_VALUE_RUNTIME(char);
+__DECL_PRINT_VALUE_RUNTIME(signed char);
+__DECL_PRINT_VALUE_RUNTIME(short);
+__DECL_PRINT_VALUE_RUNTIME(unsigned short);
+__DECL_PRINT_VALUE_RUNTIME(int);
+__DECL_PRINT_VALUE_RUNTIME(unsigned int);
+__DECL_PRINT_VALUE_RUNTIME(long);
+__DECL_PRINT_VALUE_RUNTIME(long long);
+__DECL_PRINT_VALUE_RUNTIME(unsigned long);
+__DECL_PRINT_VALUE_RUNTIME(unsigned long long);
+__DECL_PRINT_VALUE_RUNTIME(float);
+__DECL_PRINT_VALUE_RUNTIME(double);
+__DECL_PRINT_VALUE_RUNTIME(long double);
+__DECL_PRINT_VALUE_RUNTIME(char *const);
+__DECL_PRINT_VALUE_RUNTIME(char *);
+#endif
+
+namespace __repl_runtime_detail {
+
+// Custom void_t implementation for C++11 compatibility
+template <typename... Ts> struct __repl_void_impl { typedef void type; };
+
+// Helper to deduce the type of the expression 'std::begin(std::declval<T &>())'
+template <typename T>
+using __repl_begin_result = decltype(std::begin(std::declval<T &>()));
+
+// Helper to deduce the type of the expression 'std::end(std::declval<T &>())'
+template <typename T>
+using __repl_end_result = decltype(std::end(std::declval<T &>()));
+
+// Type trait to check if a type is iterable
+template <typename T, typename = void>
+struct __is_iterable : std::false_type {};
+
+template <typename T>
+struct __is_iterable<T, typename __repl_void_impl<__repl_begin_result<T>,
+                                                  __repl_end_result<T>>::type>
+    : std::true_type {};
+
+// Type trait to check if a type is std::pair
+template <typename T> struct __is_pair : std::false_type {};
+
+template <typename T, typename U>
+struct __is_pair<std::pair<T, U>> : std::true_type {};
+
+// Type trait to check if a type is std::map (or any associative container with
+// mapped_type)
+template <typename T, typename = void> struct __is_map : std::false_type {};
+
+template <typename T>
+struct __is_map<T, typename __repl_void_impl<typename T::mapped_type>::type>
+    : std::true_type {};
+
+// The type of the elements is std::pair, and the container is a map like type.
+template <
+    typename Container, typename Elt,
+    typename std::enable_if<__is_pair<Elt>::value && __is_map<Container>::value,
+                            bool>::type = true>
+std::string __PrintCollectionElt(const Elt &Val) {
+  return PrintValueRuntime(&Val.first) + " => " +
+         PrintValueRuntime(&Val.second);
+}
+
+// The type of the elements is std::pair, and the container isn't a map-like
+// type.
+template <typename Container, typename Elt,
+          typename std::enable_if<__is_pair<Elt>::value &&
+                                      !__is_map<Container>::value,
+                                  bool>::type = true>
+std::string __PrintCollectionElt(const Elt &Val) {
+  return TuplePairPrintValue(&Val);
+}
+
+template <typename Container, typename Elt,
+          typename std::enable_if<!__is_pair<Elt>::value, bool>::type = true>
+std::string __PrintCollectionElt(const Elt &Val) {
+  return PrintValueRuntime(&Val);
+}
+
+template <class Tuple, std::size_t N = std::tuple_size<Tuple>(),
+          std::size_t TupleSize = std::tuple_size<Tuple>()>
+struct __TupleLikePrinter {
+  static std::string print(const Tuple *T) {
+    constexpr std::size_t EltNum = TupleSize - N;
+    std::string Str;
+    // Not the first element.
+    if (EltNum != 0)
+      Str += ", ";
+    Str += PrintValueRuntime(&std::get<EltNum>(*T));
+    // If N+1 is not smaller than the size of the tuple,
+    // reroute the call to the printing function to the
+    // no-op specialisation to stop recursion.
+    constexpr std::size_t Nm1 = N - 1;
+    Str += __TupleLikePrinter<Tuple, Nm1>::print((const Tuple *)T);
+    return Str;
+  }
+};
+
+template <class Tuple, std::size_t TupleSize>
+struct __TupleLikePrinter<Tuple, 0, TupleSize> {
+  static std::string print(const Tuple *T) { return ""; }
+};
+
+template <class T> inline std::string TuplePairPrintValue(const T *Val) {
+  std::string Str("{ ");
+  Str += __TupleLikePrinter<T>::print(Val);
+  Str += " }";
+  return Str;
+}
+
+struct __StdVectorBool {
+  bool Value;
+  __StdVectorBool(bool V) : Value(V) {}
+};
+template <typename T>
+std::string __PrintCollectionElt(const __StdVectorBool &Val) {
+  return PrintValueRuntime(&Val.Value);
+}
+
+} // namespace __repl_runtime_detail
+
+template <typename Container,
+          typename std::enable_if<
+              __repl_runtime_detail::__is_iterable<Container>::value,
+              bool>::type = true>
+inline std::string PrintValueRuntime(const Container *C) {
+  std::string Str("{ ");
+
+  for (auto Beg = C->begin(), End = C->end(); Beg != End; Beg++) {
+    if (Beg != C->begin())
+      Str += ", ";
+    Str += __repl_runtime_detail::__PrintCollectionElt<Container>(*Beg);
+  }
+  Str += " }";
+  return Str;
+}
+
+template <typename T, size_t N>
+inline std::string PrintValueRuntime(const T (*Obj)[N]) {
+  if (N == 0)
+    return "{}";
+
+  std::string Str = "{ ";
+  for (size_t Idx = 0; Idx < N; ++Idx) {
+    Str += PrintValueRuntime(*Obj + Idx);
+    if (Idx < N - 1)
+      Str += ", ";
+  }
+  return Str + " }";
+}
+
+template <size_t N> inline std::string PrintValueRuntime(const char (*Obj)[N]) {
+  const auto *Str = reinterpret_cast<const char *const>(Obj);
+  return PrintValueRuntime(&Str);
+}
+
+// std::vector<bool>
+inline std::string PrintValueRuntime(const std::vector<bool> *Val) {
+  // Try our best to fix std::vector<bool> without too much of templated code.
+  std::vector<__repl_runtime_detail::__StdVectorBool> ValFixed(Val->begin(),
+                                                               Val->end());
+  return PrintValueRuntime<decltype(ValFixed)>(&ValFixed);
+}
+
+// tuple
+template <typename... Ts>
+inline std::string PrintValueRuntime(const std::tuple<Ts...> *Val) {
+  using T = std::tuple<Ts...>;
+  return __repl_runtime_detail::TuplePairPrintValue<T>(Val);
+}
+
+// pair
+template <typename... Ts>
+inline std::string PrintValueRuntime(const std::pair<Ts...> *Val) {
+  using T = std::pair<Ts...>;
+  return __repl_runtime_detail::TuplePairPrintValue<T>(Val);
+}
+
+// unique_ptr
+template <class T>
+inline std::string PrintValueRuntime(const std::unique_ptr<T> *Val) {
+  auto Ptr = Val->get();
+  return "std::unique_ptr -> " + PrintValueRuntime((const void **)&Ptr);
+}
+
+// shared_ptr
+template <class T>
+inline std::string PrintValueRuntime(const std::shared_ptr<T> *Val) {
+  auto Ptr = Val->get();
+  return "std::shared_ptr -> " + PrintValueRuntime((const void **)&Ptr);
+}
+
+// weak_ptr
+template <class T>
+inline std::string PrintValueRuntime(const std::weak_ptr<T> *Val) {
+  auto Ptr = Val->lock().get();
+  return "std::weak_ptr -> " + PrintValueRuntime((const void **)&Ptr);
+}
+
+// string
+template <class T>
+inline std::string PrintValueRuntime(const std::basic_string<T> *Val) {
+  const char *Chars = Val->c_str();
+  return PrintValueRuntime((const char **)&Chars);
+}
+#endif
diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt
index 9065f998f73c47..ea00bdc80f595d 100644
--- a/clang/lib/Interpreter/CMakeLists.txt
+++ b/clang/lib/Interpreter/CMakeLists.txt
@@ -20,6 +20,7 @@ add_clang_library(clangInterpreter
   Interpreter.cpp
   InterpreterUtils.cpp
   Value.cpp
+  ValuePrinter.cpp
 
   DEPENDS
   intrinsics_gen
diff --git a/clang/lib/Interpreter/DeviceOffload.cpp b/clang/lib/Interpreter/DeviceOffload.cpp
index fb42964e4936f2..9bbcce0ac0fe30 100644
--- a/clang/lib/Interpreter/DeviceOffload.cpp
+++ b/clang/lib/Interpreter/DeviceOffload.cpp
@@ -20,7 +20,7 @@
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Target/TargetMachine.h"
 
-namespace clang {
+namespace clang::caas {
 
 IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
     Interpreter &Interp, std::unique_ptr<CompilerInstance> Instance,
@@ -173,4 +173,4 @@ llvm::Error IncrementalCUDADeviceParser::GenerateFatbinary() {
 
 IncrementalCUDADeviceParser::~IncrementalCUDADeviceParser() {}
 
-} // namespace clang
+} // namespace clang::caas
diff --git a/clang/lib/Interpreter/DeviceOffload.h b/clang/lib/Interpreter/DeviceOffload.h
index ce4f218c94c79d..204f85b872cf64 100644
--- a/clang/lib/Interpreter/DeviceOffload.h
+++ b/clang/lib/Interpreter/DeviceOffload.h
@@ -17,7 +17,7 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/VirtualFileSystem.h"
 
-namespace clang {
+namespace clang::caas {
 
 class IncrementalCUDADeviceParser : public IncrementalParser {
 public:
@@ -46,6 +46,6 @@ class IncrementalCUDADeviceParser : public IncrementalParser {
   llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS;
 };
 
-} // namespace clang
+} // namespace clang::caas
 
 #endif // LLVM_CLANG_LIB_INTERPRETER_DEVICE_OFFLOAD_H
diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 40bcef94797d43..1e8fdcfef049ca 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -34,7 +34,7 @@ LLVM_ATTRIBUTE_USED void linkComponents() {
                << (void *)&llvm_orc_registerJITLoaderGDBAllocAction;
 }
 
-namespace clang {
+namespace clang::caas {
 
 IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
                                          llvm::Error &Err,
@@ -65,6 +65,10 @@ IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
 
 IncrementalExecutor::~IncrementalExecutor() {}
 
+llvm::Error IncrementalExecutor::addModule(std::unique_ptr<llvm::Module> &M) {
+  return Jit->addIRModule({std::move(M), TSCtx});
+}
+
 llvm::Error IncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
   llvm::orc::ResourceTrackerSP RT =
       Jit->getMainJITDylib().createResourceTracker();
@@ -113,4 +117,4 @@ IncrementalExecutor::getSymbolAddress(llvm::StringRef Name,
   return SymOrErr->getAddress();
 }
 
-} // end namespace clang
+} // namespace clang::caas
diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h
index dd0a210a061415..f1ea27f7d3031b 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.h
+++ b/clang/lib/Interpreter/IncrementalExecutor.h
@@ -30,9 +30,11 @@ class ThreadSafeContext;
 
 namespace clang {
 
-struct PartialTranslationUnit;
 class TargetInfo;
 
+namespace caas {
+struct PartialTranslationUnit;
+
 class IncrementalExecutor {
   using CtorDtorIterator = llvm::orc::CtorDtorIterator;
   std::unique_ptr<llvm::orc::LLJIT> Jit;
@@ -48,6 +50,7 @@ class IncrementalExecutor {
                       const clang::TargetInfo &TI);
   ~IncrementalExecutor();
 
+  llvm::Error addModule(std::unique_ptr<llvm::Module> &M);
   llvm::Error addModule(PartialTranslationUnit &PTU);
   llvm::Error removeModule(PartialTranslationUnit &PTU);
   llvm::Error runCtors() const;
@@ -57,7 +60,7 @@ class IncrementalExecutor {
 
   llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; }
 };
-
+} // namespace caas
 } // end namespace clang
 
 #endif // LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index 370bcbfee8b014..c8db113b60285e 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -29,7 +29,7 @@
 
 #include <sstream>
 
-namespace clang {
+namespace clang::caas {
 
 class IncrementalASTConsumer final : public ASTConsumer {
   Interpreter &Interp;
@@ -394,4 +394,5 @@ llvm::StringRef IncrementalParser::GetMangledName(GlobalDecl GD) const {
   assert(CG);
   return CG->GetMangledName(GD);
 }
-} // end namespace clang
+
+} // end namespace clang::caas
diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h
index e13b74c7f65948..304168a5e2b9ce 100644
--- a/clang/lib/Interpreter/IncrementalParser.h
+++ b/clang/lib/Interpreter/IncrementalParser.h
@@ -30,9 +30,11 @@ namespace clang {
 class ASTConsumer;
 class CodeGenerator;
 class CompilerInstance;
+class Parser;
+
+namespace caas {
 class IncrementalAction;
 class Interpreter;
-class Parser;
 /// Provides support for incremental compilation. Keeps track of the state
 /// changes between the subsequent incremental input.
 ///
@@ -86,6 +88,7 @@ class IncrementalParser {
 private:
   llvm::Expected<PartialTranslationUnit &> ParseOrWrapTopLevelDecl();
 };
+} // namespace caas
 } // end namespace clang
 
 #endif // LLVM_CLANG_LIB_INTERPRETER_INCREMENTALPARSER_H
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 9f97a3c6b0be9e..ef60a3f1e46efb 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -43,7 +43,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Host.h"
 using namespace clang;
-
+using namespace clang::caas;
 // FIXME: Figure out how to unify with namespace init_convenience from
 //        tools/clang-import-test/clang-import-test.cpp
 namespace {
@@ -268,6 +268,7 @@ const char *const Runtimes = R"(
       __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
     }
 #endif // __cplusplus
+    #define __CLANG_REPL__ 1
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
@@ -377,6 +378,22 @@ llvm::Error Interpreter::CreateExecutor() {
   return Err;
 }
 
+llvm::Error Interpreter::ExecuteModule(std::unique_ptr<llvm::Module> &M) {
+  if (!IncrExecutor) {
+    auto Err = CreateExecutor();
+    if (Err)
+      return Err;
+  }
+  // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
+  if (auto Err = IncrExecutor->addModule(M))
+    return Err;
+
+  if (auto Err = IncrExecutor->runCtors())
+    return Err;
+
+  return llvm::Error::success();
+}
+
 llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
   assert(T.TheModule);
   if (!IncrExecutor) {
@@ -500,6 +517,10 @@ Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) {
   return AddrOrErr;
 }
 
+std::unique_ptr<llvm::Module> Interpreter::GenModule() {
+  return IncrParser->GenModule();
+}
+
 static constexpr llvm::StringRef MagicRuntimeInterface[] = {
     "__clang_Interpreter_SetValueNoAlloc",
     "__clang_Interpreter_SetValueWithAlloc",
@@ -543,15 +564,15 @@ namespace {
 
 class RuntimeInterfaceBuilder
     : public TypeVisitor<RuntimeInterfaceBuilder, Interpreter::InterfaceKind> {
-  clang::Interpreter &Interp;
+  clang::caas::Interpreter &Interp;
   ASTContext &Ctx;
   Sema &S;
   Expr *E;
   llvm::SmallVector<Expr *, 3> Args;
 
 public:
-  RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef,
-                          Expr *VE, ArrayRef<Expr *> FixedArgs)
+  RuntimeInterfaceBuilder(clang::caas::Interpreter &In, ASTContext &C,
+                          Sema &SemaRef, Expr *VE, ArrayRef<Expr *> FixedArgs)
       : Interp(In), Ctx(C), S(SemaRef), E(VE) {
     // The Interpreter* parameter and the out parameter `OutVal`.
     for (Expr *E : FixedArgs)
diff --git a/clang/lib/Interpreter/InterpreterUtils.cpp b/clang/lib/Interpreter/InterpreterUtils.cpp
index c19cf6aa3156c9..3772b292ede52b 100644
--- a/clang/lib/Interpreter/InterpreterUtils.cpp
+++ b/clang/lib/Interpreter/InterpreterUtils.cpp
@@ -12,7 +12,7 @@
 
 #include "InterpreterUtils.h"
 
-namespace clang {
+namespace clang::caas {
 
 IntegerLiteral *IntegerLiteralExpr(ASTContext &C, uint64_t Val) {
   return IntegerLiteral::Create(C, llvm::APSInt::getUnsigned(Val),
@@ -81,7 +81,7 @@ NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name,
   else {
     const DeclContext *PrimaryWithin = nullptr;
     if (const auto *TD = dyn_cast<TagDecl>(Within))
-      PrimaryWithin = llvm::dyn_cast_or_null<DeclContext>(TD->getDefinition());
+      PrimaryWithin = dyn_cast_if_present<DeclContext>(TD->getDefinition());
     else
       PrimaryWithin = Within->getPrimaryContext();
 
@@ -97,15 +97,404 @@ NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name,
   R.resolveKind();
 
   if (R.isSingleResult())
-    return llvm::dyn_cast<NamedDecl>(R.getFoundDecl());
+    return dyn_cast<NamedDecl>(R.getFoundDecl());
 
   return nullptr;
 }
 
+static NestedNameSpecifier *CreateOuterNNS(const ASTContext &Ctx, const Decl *D,
+                                           bool FullyQualify) {
+  const DeclContext *DC = D->getDeclContext();
+  if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
+    while (NS && NS->isInline()) {
+      // Ignore inline namespace;
+      NS = dyn_cast_if_present<NamespaceDecl>(NS->getDeclContext());
+    }
+    if (NS && NS->getDeclName())
+      return CreateNestedNameSpecifier(Ctx, NS);
+    return nullptr; // no starting '::', no anonymous
+  }
+  if (const auto *TD = dyn_cast<TagDecl>(DC))
+    return CreateNestedNameSpecifier(Ctx, TD, FullyQualify);
+  if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC))
+    return CreateNestedNameSpecifier(Ctx, TDD, FullyQualify);
+  return nullptr; // no starting '::'
+}
+
+static NestedNameSpecifier *
+CreateNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *D,
+                                    bool FullyQualified) {
+  // Create a nested name specifier for the declaring context of the type.
+
+  assert(D);
+
+  const auto *Outer = dyn_cast_if_present<NamedDecl>(D->getDeclContext());
+  const auto *OuterNs = dyn_cast_if_present<NamespaceDecl>(D->getDeclContext());
+  if (Outer && !(OuterNs && OuterNs->isAnonymousNamespace())) {
+
+    if (const auto *CXXD = dyn_cast<CXXRecordDecl>(D->getDeclContext())) {
+
+      if (ClassTemplateDecl *CTD = CXXD->getDescribedClassTemplate()) {
+        // We are in the case of a type(def) that was declared in a
+        // class template but is *not* type dependent.  In clang, it gets
+        // attached to the class template declaration rather than any
+        // specific class template instantiation.   This result in 'odd'
+        // fully qualified typename:
+        //    vector<_Tp,_Alloc>::size_type
+        // Make the situation is 'useable' but looking a bit odd by
+        // picking a random instance as the declaring context.
+        // FIXME: We should not use the iterators here to check if we are in
+        // a template specialization. clTempl != cxxdecl already tell us that
+        // is the case. It seems that we rely on a side-effect from triggering
+        // deserializations to support 'some' use-case. See ROOT-9709.
+        if (CTD->spec_begin() != CTD->spec_end()) {
+          D = *(CTD->spec_begin());
+          Outer = dyn_cast<NamedDecl>(D);
+          OuterNs = dyn_cast<NamespaceDecl>(D);
+        }
+      }
+    }
+
+    if (OuterNs)
+      return CreateNestedNameSpecifier(Ctx, OuterNs);
+
+    if (const auto *TD = dyn_cast<TagDecl>(Outer))
+      return CreateNestedNameSpecifier(Ctx, TD, FullyQualified);
+  }
+  return nullptr;
+}
+
+static NestedNameSpecifier *
+CreateNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Type *TypePtr,
+                                    bool FullyQualified) {
+  // Create a nested name specifier for the declaring context of the type.
+
+  if (!TypePtr)
+    return nullptr;
+
+  Decl *D = nullptr;
+  if (const auto *TDT = dyn_cast<TypedefType>(TypePtr)) {
+    D = TDT->getDecl();
+  } else {
+    // There are probably other cases ...
+    if (const auto *TT = dyn_cast_if_present<TagType>(TypePtr))
+      D = TT->getDecl();
+    else
+      D = TypePtr->getAsCXXRecordDecl();
+  }
+
+  if (!D)
+    return nullptr;
+
+  return CreateNestedNameSpecifierForScopeOf(Ctx, D, FullyQualified);
+}
+
+static NestedNameSpecifier *
+GetFullyQualifiedNameSpecifier(const ASTContext &Ctx,
+                               NestedNameSpecifier *Scope) {
+  // Return a fully qualified version of this name specifier
+  if (Scope->getKind() == NestedNameSpecifier::Global) {
+    // Already fully qualified.
+    return Scope;
+  }
+
+  if (const Type *Type = Scope->getAsType()) {
+    // Find decl context.
+    const TagDecl *TD = nullptr;
+    if (const auto *TT = dyn_cast<TagType>(Type))
+      TD = TT->getDecl();
+    else
+      TD = Type->getAsCXXRecordDecl();
+
+    if (TD)
+      return CreateNestedNameSpecifier(Ctx, TD, true /*FullyQualified*/);
+
+    if (const auto *TDD = dyn_cast<TypedefType>(Type))
+      return CreateNestedNameSpecifier(Ctx, TDD->getDecl(),
+                                       true /*FullyQualified*/);
+  } else if (const NamespaceDecl *NS = Scope->getAsNamespace())
+    return CreateNestedNameSpecifier(Ctx, NS);
+  else if (const auto *Alias = Scope->getAsNamespaceAlias())
+    return CreateNestedNameSpecifier(Ctx,
+                                     Alias->getNamespace()->getCanonicalDecl());
+
+  return Scope;
+}
+
+static bool GetFullyQualifiedTemplateName(const ASTContext &Ctx,
+                                          TemplateName &Name) {
+
+  bool Changed = false;
+  NestedNameSpecifier *NNS = nullptr;
+
+  TemplateDecl *TD = Name.getAsTemplateDecl();
+  QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName();
+
+  if (QTN && !QTN->hasTemplateKeyword()) {
+    NNS = QTN->getQualifier();
+    NestedNameSpecifier *QNNS = GetFullyQualifiedNameSpecifier(Ctx, NNS);
+    if (QNNS != NNS) {
+      Changed = true;
+      NNS = QNNS;
+    } else {
+      NNS = nullptr;
+    }
+  } else {
+    NNS = CreateNestedNameSpecifierForScopeOf(Ctx, TD, true);
+  }
+  if (NNS) {
+    Name = Ctx.getQualifiedTemplateName(NNS,
+                                        /*TemplateKeyword=*/false,
+                                        TemplateName(TD));
+    Changed = true;
+  }
+  return Changed;
+}
+
+static bool GetFullyQualifiedTemplateArgument(const ASTContext &Ctx,
+                                              TemplateArgument &Arg) {
+  bool Changed = false;
+
+  // Note: we do not handle TemplateArgument::Expression, to replace it
+  // we need the information for the template instance decl.
+  // See GetPartiallyDesugaredTypeImpl
+
+  if (Arg.getKind() == TemplateArgument::Template) {
+    TemplateName Name = Arg.getAsTemplate();
+    Changed = GetFullyQualifiedTemplateName(Ctx, Name);
+    if (Changed) {
+      Arg = TemplateArgument(Name);
+    }
+  } else if (Arg.getKind() == TemplateArgument::Type) {
+    QualType SubTy = Arg.getAsType();
+    // Check if the type needs more desugaring and recurse.
+    QualType QTFQ = GetFullyQualifiedType(SubTy, Ctx);
+    if (QTFQ != SubTy) {
+      Arg = TemplateArgument(QTFQ);
+      Changed = true;
+    }
+  } else if (Arg.getKind() == TemplateArgument::Pack) {
+    SmallVector<TemplateArgument, 2> desArgs;
+    for (auto I = Arg.pack_begin(), E = Arg.pack_end(); I != E; ++I) {
+      TemplateArgument PackArg(*I);
+      Changed = GetFullyQualifiedTemplateArgument(Ctx, PackArg);
+      desArgs.push_back(PackArg);
+    }
+    if (Changed) {
+      // The allocator in ASTContext is mutable ...
+      // Keep the argument const to be inline will all the other interfaces
+      // like:  NestedNameSpecifier::Create
+      ASTContext &MutableCtx(const_cast<ASTContext &>(Ctx));
+      Arg = TemplateArgument::CreatePackCopy(MutableCtx, desArgs);
+    }
+  }
+  return Changed;
+}
+
+static const Type *GetFullyQualifiedLocalType(const ASTContext &Ctx,
+                                              const Type *Typeptr) {
+  // We really just want to handle the template parameter if any ....
+  // In case of template specializations iterate over the arguments and
+  // fully qualify them as well.
+  if (const auto *TST = dyn_cast<const TemplateSpecializationType>(Typeptr)) {
+
+    bool MightHaveChanged = false;
+    llvm::SmallVector<TemplateArgument, 4> DesArgs;
+    for (auto &I : TST->template_arguments()) {
+
+      // cheap to copy and potentially modified by
+      // GetFullyQualifedTemplateArgument
+      TemplateArgument Arg(I);
+      MightHaveChanged |= GetFullyQualifiedTemplateArgument(Ctx, Arg);
+      DesArgs.push_back(Arg);
+    }
+
+    // If desugaring happened allocate new type in the AST.
+    if (MightHaveChanged) {
+      QualType QT = Ctx.getTemplateSpecializationType(
+          TST->getTemplateName(), DesArgs, TST->getCanonicalTypeInternal());
+      return QT.getTypePtr();
+    }
+  } else if (const auto *TSTRecord = dyn_cast<const RecordType>(Typeptr)) {
+    // We are asked to fully qualify and we have a Record Type,
+    // which can point to a template instantiation with no sugar in any of
+    // its template argument, however we still need to fully qualify them.
+
+    if (const auto *TSTdecl =
+            dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl())) {
+      const TemplateArgumentList &TemplateArgs = TSTdecl->getTemplateArgs();
+
+      bool MightHaveChanged = false;
+      llvm::SmallVector<TemplateArgument, 4> DesArgs;
+      for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) {
+
+        // cheap to copy and potentially modified by
+        // GetFullyQualifedTemplateArgument
+        TemplateArgument Arg(TemplateArgs[I]);
+        MightHaveChanged |= GetFullyQualifiedTemplateArgument(Ctx, Arg);
+        DesArgs.push_back(Arg);
+      }
+
+      // If desugaring happened allocate new type in the AST.
+      if (MightHaveChanged) {
+        TemplateName TN(TSTdecl->getSpecializedTemplate());
+        QualType QT = Ctx.getTemplateSpecializationType(
+            TN, DesArgs, TSTRecord->getCanonicalTypeInternal());
+        return QT.getTypePtr();
+      }
+    }
+  }
+  return Typeptr;
+}
+
+NestedNameSpecifier *CreateNestedNameSpecifier(const ASTContext &Ctx,
+                                               const NamespaceDecl *NSD) {
+  while (NSD && NSD->isInline()) {
+    // Ignore inline namespace;
+    NSD = dyn_cast_if_present<NamespaceDecl>(NSD->getDeclContext());
+  }
+  if (!NSD)
+    return nullptr;
+
+  bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces
+  return NestedNameSpecifier::Create(
+      Ctx, CreateOuterNNS(Ctx, NSD, FullyQualified), NSD);
+}
+
+NestedNameSpecifier *CreateNestedNameSpecifier(const ASTContext &Ctx,
+                                               const TypedefNameDecl *TD,
+                                               bool FullyQualify) {
+  return NestedNameSpecifier::Create(Ctx, CreateOuterNNS(Ctx, TD, FullyQualify),
+                                     /*Template=*/true, TD->getTypeForDecl());
+}
+
+NestedNameSpecifier *CreateNestedNameSpecifier(const ASTContext &Ctx,
+                                               const TagDecl *TD,
+                                               bool FullyQualify) {
+  const Type *Ty = Ctx.getTypeDeclType(TD).getTypePtr();
+  if (FullyQualify)
+    Ty = GetFullyQualifiedLocalType(Ctx, Ty);
+  return NestedNameSpecifier::Create(Ctx, CreateOuterNNS(Ctx, TD, FullyQualify),
+                                     /*Template=*/false, Ty);
+}
+
+QualType GetFullyQualifiedType(QualType QT, const ASTContext &Ctx) {
+  // Return the fully qualified type, if we need to recurse through any
+  // template parameter, this needs to be merged somehow with
+  // GetPartialDesugaredType.
+
+  // In case of myType* we need to strip the pointer first, fully qualifiy
+  // and attach the pointer once again.
+  if (isa<PointerType>(QT.getTypePtr())) {
+    // Get the qualifiers.
+    Qualifiers Quals = QT.getQualifiers();
+    QT = GetFullyQualifiedType(QT->getPointeeType(), Ctx);
+    QT = Ctx.getPointerType(QT);
+    // Add back the qualifiers.
+    QT = Ctx.getQualifiedType(QT, Quals);
+    return QT;
+  }
+
+  // In case of myType& we need to strip the pointer first, fully qualifiy
+  // and attach the pointer once again.
+  if (isa<ReferenceType>(QT.getTypePtr())) {
+    // Get the qualifiers.
+    bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
+    Qualifiers Quals = QT.getQualifiers();
+    QT = GetFullyQualifiedType(QT->getPointeeType(), Ctx);
+    // Add the r- or l-value reference type back to the desugared one.
+    if (IsLValueRefTy)
+      QT = Ctx.getLValueReferenceType(QT);
+    else
+      QT = Ctx.getRValueReferenceType(QT);
+    // Add back the qualifiers.
+    QT = Ctx.getQualifiedType(QT, Quals);
+    return QT;
+  }
+
+  // Strip deduced types.
+  if (const auto *AutoTy = dyn_cast<AutoType>(QT.getTypePtr())) {
+    if (!AutoTy->getDeducedType().isNull())
+      return GetFullyQualifiedType(
+          AutoTy->getDeducedType().getDesugaredType(Ctx), Ctx);
+  }
+
+  // Remove the part of the type related to the type being a template
+  // parameter (we won't report it as part of the 'type name' and it is
+  // actually make the code below to be more complex (to handle those)
+  while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) {
+    // Get the qualifiers.
+    Qualifiers Quals = QT.getQualifiers();
+
+    QT = cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar();
+
+    // Add back the qualifiers.
+    QT = Ctx.getQualifiedType(QT, Quals);
+  }
+
+  NestedNameSpecifier *Prefix = nullptr;
+  Qualifiers PrefixQualifiers;
+  if (const auto *EType = dyn_cast<ElaboratedType>(QT.getTypePtr())) {
+    // Intentionally, we do not care about the other compononent of
+    // the elaborated type (the keyword) as part of the partial
+    // desugaring (and/or name normalization) is to remove it.
+    Prefix = EType->getQualifier();
+    if (Prefix) {
+      const NamespaceDecl *NS = Prefix->getAsNamespace();
+      if (Prefix != NestedNameSpecifier::GlobalSpecifier(Ctx) &&
+          !(NS && NS->isAnonymousNamespace())) {
+        PrefixQualifiers = QT.getLocalQualifiers();
+        Prefix = GetFullyQualifiedNameSpecifier(Ctx, Prefix);
+        QT = QualType(EType->getNamedType().getTypePtr(), 0);
+      } else {
+        Prefix = nullptr;
+      }
+    }
+  } else {
+
+    // Create a nested name specifier if needed (i.e. if the decl context
+    // is not the global scope.
+    Prefix = CreateNestedNameSpecifierForScopeOf(Ctx, QT.getTypePtr(),
+                                                 true /*FullyQualified*/);
+
+    // move the qualifiers on the outer type (avoid 'std::const string'!)
+    if (Prefix) {
+      PrefixQualifiers = QT.getLocalQualifiers();
+      QT = QualType(QT.getTypePtr(), 0);
+    }
+  }
+
+  // In case of template specializations iterate over the arguments and
+  // fully qualify them as well.
+  if (isa<const TemplateSpecializationType>(QT.getTypePtr())) {
+
+    Qualifiers Qualifiers = QT.getLocalQualifiers();
+    const Type *TypePtr = GetFullyQualifiedLocalType(Ctx, QT.getTypePtr());
+    QT = Ctx.getQualifiedType(TypePtr, Qualifiers);
+
+  } else if (isa<const RecordType>(QT.getTypePtr())) {
+    // We are asked to fully qualify and we have a Record Type,
+    // which can point to a template instantiation with no sugar in any of
+    // its template argument, however we still need to fully qualify them.
+
+    Qualifiers Qualifiers = QT.getLocalQualifiers();
+    const Type *TypePtr = GetFullyQualifiedLocalType(Ctx, QT.getTypePtr());
+    QT = Ctx.getQualifiedType(TypePtr, Qualifiers);
+  }
+  if (Prefix) {
+    // We intentionally always use ETK_None, we never want
+    // the keyword (humm ... what about anonymous types?)
+    QT = Ctx.getElaboratedType(ETK_None, Prefix, QT);
+    QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
+  }
+  return QT;
+}
+
 std::string GetFullTypeName(ASTContext &Ctx, QualType QT) {
+  QualType FQT = GetFullyQualifiedType(QT, Ctx);
   PrintingPolicy Policy(Ctx.getPrintingPolicy());
   Policy.SuppressScope = false;
   Policy.AnonymousTagLocations = false;
-  return QT.getAsString(Policy);
+  return FQT.getAsString(Policy);
 }
-} // namespace clang
+} // namespace clang::caas
diff --git a/clang/lib/Interpreter/InterpreterUtils.h b/clang/lib/Interpreter/InterpreterUtils.h
index 8df158c17d4919..61c1cab822208c 100644
--- a/clang/lib/Interpreter/InterpreterUtils.h
+++ b/clang/lib/Interpreter/InterpreterUtils.h
@@ -33,7 +33,7 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/TargetParser/Host.h"
 
-namespace clang {
+namespace clang::caas {
 IntegerLiteral *IntegerLiteralExpr(ASTContext &C, uint64_t Val);
 
 Expr *CStyleCastPtrExpr(Sema &S, QualType Ty, Expr *E);
@@ -48,7 +48,25 @@ NamespaceDecl *LookupNamespace(Sema &S, llvm::StringRef Name,
 NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name,
                        const DeclContext *Within);
 
+NestedNameSpecifier *CreateNestedNameSpecifier(const ASTContext &Ctx,
+                                               const NamespaceDecl *Namesp);
+
+NestedNameSpecifier *CreateNestedNameSpecifier(const ASTContext &Ctx,
+                                               const TypedefNameDecl *TD,
+                                               bool FullyQualify);
+
+NestedNameSpecifier *CreateNestedNameSpecifier(const ASTContext &Ctx,
+                                               const TagDecl *TD,
+                                               bool FullyQualify);
+
+QualType GetFullyQualifiedType(QualType QT, const ASTContext &Ctx);
+
 std::string GetFullTypeName(ASTContext &Ctx, QualType QT);
-} // namespace clang
+
+class Value;
+
+std::string ReplPrintTypeImpl(const Value &);
+std::string ReplPrintDataImpl(const Value &);
+} // namespace clang::caas
 
 #endif
diff --git a/clang/lib/Interpreter/Value.cpp b/clang/lib/Interpreter/Value.cpp
index 1d6b2da087e9fb..521b663833e680 100644
--- a/clang/lib/Interpreter/Value.cpp
+++ b/clang/lib/Interpreter/Value.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Interpreter/Value.h"
+#include "InterpreterUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Type.h"
 #include "clang/Interpreter/Interpreter.h"
@@ -23,6 +24,7 @@
 #include <utility>
 
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 
@@ -231,6 +233,11 @@ void *Value::getPtr() const {
   return Data.m_Ptr;
 }
 
+void **Value::getPtrAddress() const {
+  assert(ValueKind == K_PtrOrObj);
+  return &const_cast<Value *>(this)->Data.m_Ptr;
+}
+
 QualType Value::getType() const {
   return QualType::getFromOpaquePtr(OpaqueType);
 }
@@ -256,12 +263,30 @@ const ASTContext &Value::getASTContext() const {
 void Value::dump() const { print(llvm::outs()); }
 
 void Value::printType(llvm::raw_ostream &Out) const {
-  Out << "Not implement yet.\n";
+  Out << ReplPrintTypeImpl(*this);
 }
+
 void Value::printData(llvm::raw_ostream &Out) const {
-  Out << "Not implement yet.\n";
+  Out << ReplPrintDataImpl(*this);
 }
+// FIXME: We do not support the multiple inheritance case where one of the base
+// classes has a pretty-printer and the other does not.
 void Value::print(llvm::raw_ostream &Out) const {
   assert(OpaqueType != nullptr && "Can't print default Value");
-  Out << "Not implement yet.\n";
+
+  // Don't even try to print a void or an invalid type, it doesn't make sense.
+  if (getType()->isVoidType() || !isValid())
+    return;
+
+  // We need to get all the results together then print it, since `printType` is
+  // much faster than `printData`.
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+
+  SS << "(";
+  printType(SS);
+  SS << ") ";
+  printData(SS);
+  SS << "\n";
+  Out << Str;
 }
diff --git a/clang/lib/Interpreter/ValuePrinter.cpp b/clang/lib/Interpreter/ValuePrinter.cpp
new file mode 100644
index 00000000000000..a80a1960d05780
--- /dev/null
+++ b/clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,562 @@
+//===--- ValuePrinter.cpp - Utils for value printing --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements routines for value printing in clang-repl.
+//
+//===----------------------------------------------------------------------===//
+#include "InterpreterUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Type.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Interpreter/Interpreter.h"
+#include "clang/Interpreter/Value.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <string>
+
+using namespace clang;
+using namespace clang::caas;
+
+static std::string PrintDeclType(const QualType &QT, NamedDecl *D) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  if (QT.hasQualifiers())
+    SS << QT.getQualifiers().getAsString() << " ";
+  SS << D->getQualifiedNameAsString();
+  return Str;
+}
+
+static std::string PrintQualType(ASTContext &Ctx, QualType QT) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  PrintingPolicy Policy(Ctx.getPrintingPolicy());
+  // Print the Allocator in STL containers, for instance.
+  Policy.SuppressDefaultTemplateArgs = false;
+  Policy.SuppressUnwrittenScope = true;
+  // Print 'a<b<c> >' rather than 'a<b<c>>'.
+  Policy.SplitTemplateClosers = true;
+
+  struct LocalPrintingPolicyRAII {
+    ASTContext &Context;
+    PrintingPolicy Policy;
+
+    LocalPrintingPolicyRAII(ASTContext &Ctx, PrintingPolicy &PP)
+        : Context(Ctx), Policy(Ctx.getPrintingPolicy()) {
+      Context.setPrintingPolicy(PP);
+    }
+    ~LocalPrintingPolicyRAII() { Context.setPrintingPolicy(Policy); }
+  } X(Ctx, Policy);
+
+  const QualType NonRefTy = QT.getNonReferenceType();
+
+  if (const auto *TTy = llvm::dyn_cast<TagType>(NonRefTy))
+    SS << PrintDeclType(NonRefTy, TTy->getDecl());
+  else if (const auto *TRy = dyn_cast<RecordType>(NonRefTy))
+    SS << PrintDeclType(NonRefTy, TRy->getDecl());
+  else {
+    const QualType Canon = NonRefTy.getCanonicalType();
+    if (Canon->isBuiltinType() && !NonRefTy->isFunctionPointerType() &&
+        !NonRefTy->isMemberPointerType()) {
+      SS << Canon.getAsString(Ctx.getPrintingPolicy());
+    } else if (const auto *TDTy = dyn_cast<TypedefType>(NonRefTy)) {
+      // FIXME: TemplateSpecializationType & SubstTemplateTypeParmType checks
+      // are predominately to get STL containers to print nicer and might be
+      // better handled in GetFullyQualifiedName.
+      //
+      // std::vector<Type>::iterator is a TemplateSpecializationType
+      // std::vector<Type>::value_type is a SubstTemplateTypeParmType
+      //
+      QualType SSDesugar = TDTy->getLocallyUnqualifiedSingleStepDesugaredType();
+      if (llvm::isa<SubstTemplateTypeParmType>(SSDesugar))
+        SS << GetFullTypeName(Ctx, Canon);
+      else if (llvm::isa<TemplateSpecializationType>(SSDesugar))
+        SS << GetFullTypeName(Ctx, NonRefTy);
+      else
+        SS << PrintDeclType(NonRefTy, TDTy->getDecl());
+    } else
+      SS << GetFullTypeName(Ctx, NonRefTy);
+  }
+
+  if (QT->isReferenceType())
+    SS << " &";
+
+  return Str;
+}
+
+static std::string PrintEnum(const Value &V) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  ASTContext &Ctx = const_cast<ASTContext &>(V.getASTContext());
+
+  QualType DesugaredTy = V.getType().getDesugaredType(Ctx);
+  const EnumType *EnumTy = DesugaredTy.getNonReferenceType()->getAs<EnumType>();
+  assert(EnumTy && "Fail to cast to enum type");
+
+  EnumDecl *ED = EnumTy->getDecl();
+  uint64_t Data = V.getULongLong();
+  bool IsFirst = true;
+  llvm::APSInt AP = Ctx.MakeIntValue(Data, DesugaredTy);
+
+  for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; ++I) {
+    if (I->getInitVal() == AP) {
+      if (!IsFirst)
+        SS << " ? ";
+      SS << "(" + I->getQualifiedNameAsString() << ")";
+      IsFirst = false;
+    }
+  }
+
+  SS << " : " << PrintQualType(Ctx, ED->getIntegerType()) << " "
+     << llvm::toString(AP, /*Radix=*/10);
+  return Str;
+}
+
+static std::string PrintFunction(const Value &V, const void *Ptr) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << "Function @" << Ptr;
+
+  const FunctionDecl *FD = nullptr;
+
+  auto Decls = V.getASTContext().getTranslationUnitDecl()->decls();
+  assert(std::distance(Decls.begin(), Decls.end()) == 1 &&
+         "TU should only contain one Decl");
+  auto *TLSD = llvm::cast<TopLevelStmtDecl>(*Decls.begin());
+
+  // Get __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void
+  // *OpaqueType, void *Val);
+  if (auto *InterfaceCall = llvm::dyn_cast<CallExpr>(TLSD->getStmt())) {
+    const auto *Arg = InterfaceCall->getArg(/*Val*/ 3);
+    // Get rid of cast nodes.
+    while (const CastExpr *CastE = llvm::dyn_cast<CastExpr>(Arg))
+      Arg = CastE->getSubExpr();
+    if (const DeclRefExpr *DeclRefExp = llvm::dyn_cast<DeclRefExpr>(Arg))
+      FD = llvm::dyn_cast<FunctionDecl>(DeclRefExp->getDecl());
+
+    if (FD) {
+      SS << '\n';
+      const clang::FunctionDecl *FDef;
+      if (FD->hasBody(FDef))
+        FDef->print(SS);
+    }
+  }
+  return Str;
+}
+
+static std::string PrintAddress(const void *Ptr, char Prefix) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  if (!Ptr)
+    return Str;
+  SS << Prefix << Ptr;
+  return Str;
+}
+
+// FIXME: Encodings. Handle unprintable characters such as control characters.
+static std::string PrintOneChar(char Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+
+  SS << "'" << Val << "'";
+  return Str;
+}
+
+// Char pointers
+// Assumption is this is a string.
+// N is limit to prevent endless loop if Ptr is not really a string.
+static std::string PrintString(const char *const *Ptr, size_t N = 10000) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+
+  const char *Start = *Ptr;
+  if (!Start)
+    return "nullptr";
+
+  const char *End = Start + N;
+  // If we're gonnd do this, better make sure the end is valid too
+  // FIXME: getpagesize() & GetSystemInfo().dwPageSize might be better
+  static constexpr auto PAGE_SIZE = 1024;
+  while (N > 1024) {
+    N -= PAGE_SIZE;
+    End = Start + N;
+  }
+
+  if (*Start == 0)
+    return "\"\"";
+
+  // Copy the bytes until we get a null-terminator
+  SS << "\"";
+  while (Start < End && *Start)
+    SS << *Start++;
+  SS << "\"";
+
+  return Str;
+}
+
+// Build the CallExpr to `PrintValueRuntime`.
+static void BuildWrapperBody(Interpreter &Interp, Sema &S, ASTContext &Ctx,
+                             FunctionDecl *WrapperFD, QualType QT,
+                             const void *ValPtr) {
+  Sema::SynthesizedFunctionScope SemaFScope(S, WrapperFD);
+  clang::DeclarationName RuntimeCallName =
+      S.PP.getIdentifierInfo("PrintValueRuntime");
+  clang::LookupResult R(S, RuntimeCallName, SourceLocation(),
+                        clang::Sema::LookupOrdinaryName);
+  S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl());
+
+  Expr *OverldExpr = UnresolvedLookupExpr::Create(
+      Ctx, /*NamingClass=*/nullptr, NestedNameSpecifierLoc(),
+      clang::DeclarationNameInfo(RuntimeCallName, SourceLocation()),
+      /*RequiresADL*/ false, R.isOverloadedResult(), R.begin(), R.end());
+
+  if (const auto *AT = llvm::dyn_cast<AutoType>(QT.getTypePtr())) {
+    if (AT->isDeduced())
+      QT = AT->getDeducedType().getDesugaredType(Ctx);
+  }
+
+  if (const auto *PT = llvm::dyn_cast<PointerType>(QT.getTypePtr())) {
+    // Normalize `X*` to `const void*`, invoke `printValue(const void**)`,
+    // unless it's a character string.
+    QualType QTPointeeUnqual = PT->getPointeeType().getUnqualifiedType();
+    if (!Ctx.hasSameType(QTPointeeUnqual, Ctx.CharTy) &&
+        !Ctx.hasSameType(QTPointeeUnqual, Ctx.WCharTy) &&
+        !Ctx.hasSameType(QTPointeeUnqual, Ctx.Char16Ty) &&
+        !Ctx.hasSameType(QTPointeeUnqual, Ctx.Char32Ty)) {
+      QT = Ctx.getPointerType(Ctx.VoidTy.withConst());
+    }
+  } else if (const auto *RTy = llvm::dyn_cast<ReferenceType>(QT.getTypePtr())) {
+    // X& will be printed as X* (the pointer will be added below).
+    QT = RTy->getPointeeType();
+    // Val will be a X**, but we cast this to X*, so dereference here:
+    ValPtr = *(const void *const *)ValPtr;
+  }
+
+  // `PrintValueRuntime()` takes the *address* of the value to be printed:
+  QualType QTPtr = Ctx.getPointerType(QT);
+  Expr *TypeArg = CStyleCastPtrExpr(S, QTPtr, (uintptr_t)ValPtr);
+  llvm::SmallVector<Expr *, 1> CallArgs = {TypeArg};
+
+  // Create the CallExpr.
+  ExprResult RuntimeCall =
+      S.ActOnCallExpr(S.getCurScope(), OverldExpr, SourceLocation(), CallArgs,
+                      SourceLocation());
+  assert(!RuntimeCall.isInvalid() && "Cannot create call to PrintValueRuntime");
+
+  // Create the ReturnStmt.
+  StmtResult RetStmt =
+      S.ActOnReturnStmt(SourceLocation(), RuntimeCall.get(), S.getCurScope());
+  assert(!RetStmt.isInvalid() && "Cannot create ReturnStmt");
+
+  // Create the CompoundStmt.
+  StmtResult Body =
+      CompoundStmt::Create(Ctx, {RetStmt.get()}, FPOptionsOverride(),
+                           SourceLocation(), SourceLocation());
+  assert(!Body.isInvalid() && "Cannot create function body");
+
+  WrapperFD->setBody(Body.get());
+  // Add attribute `__attribute__((used))`.
+  WrapperFD->addAttr(UsedAttr::CreateImplicit(Ctx));
+}
+
+static constexpr const char *const WrapperName = "__InterpreterCallPrint";
+
+static llvm::Expected<llvm::orc::ExecutorAddr> CompileDecl(Interpreter &Interp,
+                                                           Decl *D) {
+  assert(D && "The Decl being compiled can't be null");
+
+  ASTConsumer &Consumer = Interp.getCompilerInstance()->getASTConsumer();
+  Consumer.HandleTopLevelDecl(DeclGroupRef(D));
+  Interp.getCompilerInstance()->getSema().PerformPendingInstantiations();
+  Consumer.HandleTranslationUnit(Interp.getASTContext());
+
+  if (std::unique_ptr<llvm::Module> M = Interp.GenModule()) {
+    if (llvm::Error Err = Interp.ExecuteModule(M))
+      return Err;
+    ASTNameGenerator ASTNameGen(Interp.getASTContext());
+    llvm::Expected<llvm::orc::ExecutorAddr> AddrOrErr =
+        Interp.getSymbolAddressFromLinkerName(ASTNameGen.getName(D));
+
+    return AddrOrErr;
+  }
+  return llvm::orc::ExecutorAddr{};
+}
+
+static std::string CreateUniqName(std::string Base) {
+  static size_t I = 0;
+  Base += std::to_string(I);
+  I += 1;
+  return Base;
+}
+
+static std::string SynthesizeRuntimePrint(const Value &V) {
+  Interpreter &Interp = const_cast<Interpreter &>(V.getInterpreter());
+  Sema &S = Interp.getCompilerInstance()->getSema();
+  ASTContext &Ctx = S.getASTContext();
+
+  // Only include this header once and on demand. Because it's very heavy.
+  static bool Included = false;
+  if (!Included) {
+    Included = true;
+    llvm::cantFail(
+        Interp.Parse("#include <__clang_interpreter_runtime_printvalue.h>"));
+  }
+  // Lookup std::string.
+  NamespaceDecl *Std = LookupNamespace(S, "std");
+  assert(Std && "Cannot find namespace std");
+  Decl *StdStringDecl = LookupNamed(S, "string", Std);
+  assert(StdStringDecl && "Cannot find std::string");
+  const auto *StdStringTyDecl = llvm::dyn_cast<TypeDecl>(StdStringDecl);
+  assert(StdStringTyDecl && "Cannot find type of std::string");
+
+  // Create the wrapper function.
+  DeclarationName DeclName = &Ctx.Idents.get(CreateUniqName(WrapperName));
+  QualType RetTy(StdStringTyDecl->getTypeForDecl(), 0);
+  QualType FnTy =
+      Ctx.getFunctionType(RetTy, {}, FunctionProtoType::ExtProtoInfo());
+  auto *WrapperFD = FunctionDecl::Create(
+      Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
+      DeclName, FnTy, Ctx.getTrivialTypeSourceInfo(FnTy), SC_None);
+
+  void *ValPtr = V.getPtr();
+  if (!V.isManuallyAlloc())
+    ValPtr = V.getPtrAddress();
+
+  BuildWrapperBody(Interp, S, Ctx, WrapperFD, V.getType(), ValPtr);
+
+  auto AddrOrErr = CompileDecl(Interp, WrapperFD);
+  if (!AddrOrErr)
+    llvm::logAllUnhandledErrors(AddrOrErr.takeError(), llvm::errs(),
+                                "Fail to get symbol address");
+  if (auto *Main = AddrOrErr->toPtr<std::string (*)()>())
+    return (*Main)();
+  return "Error to print the value!";
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const void *Ptr) {
+  return PrintAddress(Ptr, '@');
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const void **Ptr) {
+  return PrintAddress(*Ptr, '@');
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const bool *Val) {
+  if (*Val)
+    return "true";
+  return "false";
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const char *Val) {
+  return PrintOneChar(*Val);
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const signed char *Val) {
+  return PrintOneChar(*Val);
+}
+
+REPL_EXTERNAL_VISIBILITY std::string
+PrintValueRuntime(const unsigned char *Val) {
+  return PrintOneChar(*Val);
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const short *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << *Val;
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string
+PrintValueRuntime(const unsigned short *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << *Val;
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const int *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << *Val;
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string
+PrintValueRuntime(const unsigned int *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << *Val;
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const long *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << *Val;
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const long long *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << *Val;
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string
+PrintValueRuntime(const unsigned long *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << *Val;
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string
+PrintValueRuntime(const unsigned long long *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << *Val;
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const float *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << llvm::format("%#.6g", *Val) << 'f';
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const double *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << llvm::format("%#.12g", *Val);
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const long double *Val) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  SS << llvm::format("%#.8Lg", *Val) << 'L';
+  return Str;
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const char *const *Val) {
+  return PrintString(Val);
+}
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const char **Val) {
+  return PrintString(Val);
+}
+
+template <typename T> static std::string PrintValueWrapper(const T &Val) {
+  return PrintValueRuntime(&Val);
+}
+
+namespace clang::caas {
+std::string ReplPrintDataImpl(const Value &V) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+
+  QualType QT = V.getType();
+  QualType DesugaredTy = QT.getDesugaredType(V.getASTContext());
+  QualType NonRefTy = DesugaredTy.getNonReferenceType();
+
+  if (NonRefTy->isNullPtrType())
+    SS << "nullptr\n";
+  else if (NonRefTy->isEnumeralType())
+    return PrintEnum(V);
+  else if (NonRefTy->isFunctionType())
+    return PrintFunction(V, &V);
+  else if ((NonRefTy->isPointerType() || NonRefTy->isMemberPointerType()) &&
+           NonRefTy->getPointeeType()->isFunctionProtoType())
+    return PrintFunction(V, V.getPtr());
+  else if (auto *BT = DesugaredTy.getCanonicalType()->getAs<BuiltinType>()) {
+    switch (BT->getKind()) {
+    case BuiltinType::Bool: {
+      SS << PrintValueWrapper(V.getBool());
+      break;
+    }
+    case BuiltinType::Char_S:
+    case BuiltinType::SChar: {
+      SS << PrintValueWrapper(V.getSChar());
+      break;
+    }
+    case BuiltinType::Short: {
+      SS << PrintValueWrapper(V.getShort());
+      break;
+    }
+    case BuiltinType::Int: {
+      SS << PrintValueWrapper(V.getInt());
+      break;
+    }
+    case BuiltinType::Long: {
+      SS << PrintValueWrapper(V.getLong());
+      break;
+    }
+    case BuiltinType::LongLong: {
+      SS << PrintValueWrapper(V.getLongLong());
+      break;
+    }
+    case BuiltinType::Char_U:
+    case BuiltinType::UChar: {
+      SS << PrintValueWrapper(V.getUChar());
+      break;
+    }
+    case BuiltinType::UShort: {
+      SS << PrintValueWrapper(V.getUShort());
+      break;
+    }
+    case BuiltinType::UInt: {
+      SS << PrintValueWrapper(V.getUInt());
+      break;
+    }
+    case BuiltinType::ULong: {
+      SS << PrintValueWrapper(V.getULong());
+      break;
+    }
+    case BuiltinType::ULongLong: {
+      SS << PrintValueWrapper(V.getULongLong());
+      break;
+    }
+    case BuiltinType::Float: {
+      SS << PrintValueWrapper(V.getFloat());
+      break;
+    }
+    case BuiltinType::Double: {
+      SS << PrintValueWrapper(V.getDouble());
+      break;
+    }
+    case BuiltinType::LongDouble: {
+      SS << PrintValueWrapper(V.getLongDouble());
+      break;
+    }
+    default:
+      llvm_unreachable("Unknown Builtintype kind");
+    }
+  } else if (auto *CXXRD = NonRefTy->getAsCXXRecordDecl();
+             CXXRD && CXXRD->isLambda()) {
+    SS << PrintAddress(V.getPtr(), '@');
+  } else {
+    // All fails then generate a runtime call, this is slow.
+    SS << SynthesizeRuntimePrint(V);
+  }
+  return Str;
+}
+
+std::string ReplPrintTypeImpl(const Value &V) {
+  ASTContext &Ctx = const_cast<ASTContext &>(V.getASTContext());
+  QualType QT = V.getType();
+
+  return PrintQualType(Ctx, QT);
+}
+} // namespace clang::caas
diff --git a/clang/test/Interpreter/pretty-print.cpp b/clang/test/Interpreter/pretty-print.cpp
new file mode 100644
index 00000000000000..6a489d3550aa0b
--- /dev/null
+++ b/clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,206 @@
+// RUN: clang-repl "int i = 10;" 'extern "C" int printf(const char*,...);' \
+// RUN:            'auto r1 = printf("i = %d\n", i);' | FileCheck --check-prefix=CHECK-DRIVER %s
+// UNSUPPORTED: system-aix
+// CHECK-DRIVER: i = 10
+// RUN: cat %s | clang-repl -Xcc -std=c++11 -Xcc -fno-delayed-template-parsing | FileCheck %s
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+struct NonPOD {        \
+  static int sI;       \
+  int I;               \
+  NonPOD(): I(sI++) {} \
+};
+const char* PrintValueRuntime(const NonPOD* type) {             \
+  switch (type->I) {                                            \
+  default: return "out-of-bounds";                              \
+  case 0: return "0"; case 1: return "1"; case 2: return "2";   \
+  case 3: return "3"; case 4: return "4"; case 5: return "5";   \
+  }                                                             \
+}
+
+int NonPOD::sI = 0;
+
+NonPOD non_pod_arr[2][3];
+// Check array order after the value printing transformation. Also make sure we
+// can handle the forward declaration of operator new with placement.
+non_pod_arr
+// CHECK-NEXT: (NonPOD[2][3]) { { 0, 1, 2 }, { 3, 4, 5 } }
+
+const char* c_str = "Goodbye, world!";
+c_str
+// CHECK-NEXT: (const char *) "Goodbye, world!"
+
+const char* c_null_str = 0;
+c_null_str
+// CHECK-NEXT: (const char *) nullptr
+
+"Hello, world"
+// CHECK-NEXT: (const char[13]) "Hello, world"
+
+int x = 42;
+x
+// CHECK-NEXT: (int) 42
+
+&x
+// CHECK-NEXT: (int *) @0x{{[0-9a-f]+}}
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.20000f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.21000000000
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) @0x{{[0-9a-f]+}}
+
+S1{}
+// CHECK-NEXT: (S1) @0x{{[0-9a-f]+}}
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) @0x{{[0-9a-f]+}}
+E.d
+// CHECK-NEXT: (int) 22
+
+struct S3 { int* p; S3() { p = new int(42); } ~S3() { delete p; } };
+S3{}
+// CHECK-NEXT: (S3) @0x{{[0-9a-f]+}}
+S3 s3;
+s3
+// CHECK-NEXT: (S3 &) @0x{{[0-9a-f]+}}
+
+struct S4 { ~S4() { printf("~S4()\n"); }};
+S4{}
+// CHECK-NEXT: (S4) @0x{{[0-9a-f]+}}
+
+enum Enum{ e1 = -12, e2, e3=33, e4, e5 = 33};
+e2
+// CHECK-NEXT: (Enum) (e2) : int -11
+::e1
+// CHECK-NEXT: (Enum) (e1) : int -12
+
+enum class Color { Black = 0, Red, Green };
+Color::Black
+// CHECK-NEXT: (Color) (Color::Black) : int 0
+
+// Arrays.
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+
+// Lambdas.
+
+auto Lambda1 = []{};
+Lambda1
+// CHECK-NEXT: ((lambda) &) @0x{{[0-9a-f]+}}
+[]{}
+// CHECK-NEXT: ((lambda at input_line_{{[0-9]+}}:1:1)) @0x{{[0-9a-f]+}}
+
+template<int n> struct F{ enum {RET=F<n-1>::RET*n} ; };
+template<> struct F<0> { enum {RET = 1}; };
+F<7>::RET
+// CHECK-NEXT: (F<7>::(unnamed enum at input_line_{{[0-9]+}}:1:27)) (F<7>::RET) : unsigned int 5040
+
+int foo() { return 42; }
+foo()
+// CHECK-NEXT: (int) 42
+
+void bar() {}
+bar()
+
+struct S5 { int foo() { return 42; }};
+&S5::foo
+// CHECK-NEXT: (int (S5::*)()) Function @0x{{[0-9a-f]+}}
+
+#include <memory>
+
+auto p1 = std::make_shared<int>(42);
+p1
+// CHECK-NEXT: (std::shared_ptr<int> &) std::shared_ptr -> @0x{{[0-9a-f]+}}
+
+std::unique_ptr<int> p2(new int(42));
+p2
+// CHECK-NEXT: (std::unique_ptr<int> &) std::unique_ptr -> @0x{{[0-9a-f]+}}
+
+#include <array>
+std::array<int, 3> a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array<int, 3> &) { 1, 2, 3 }
+
+#include <vector>
+std::vector<int> v1 = {7, 5, 16, 8};
+v1
+// CHECK-NEXT: (std::vector<int> &) { 7, 5, 16, 8 }
+
+std::vector<bool> v = {true, false, true};
+v
+// CHECK-NEXT: (std::vector<bool> &) { true, false, true }
+
+#include <deque>
+std::deque<int> dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque<int> &) { 7, 5, 16, 8 }
+
+#include <forward_list>
+std::forward_list<int> fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list<int> &) { 3, 4, 5, 6 }
+
+#include <set>
+std::set<int> z1 = {2,4,6,8};
+z1
+// CHECK-NEXT: (std::set<int> &) { 2, 4, 6, 8 }
+
+#include <unordered_set>
+std::unordered_set<int> z2 = {8,2,4,6};
+z2
+// CHECK-NEXT: (std::unordered_set<int> &) { [[Num:[0-9]+]], [[Num:[0-9]+]], [[Num:[0-9]+]], [[Num:[0-9]+]] }
+
+std::multiset<int> e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset<int> &) { 1, 2, 2, 3, 3, 4, 7 }
+
+#include <string>
+std::string std_str = "Hello, world!";
+std_str
+// CHECK-NEXT: (std::string &) "Hello, world!"
+
+#include <utility>
+std::pair<int,char> pr(42,'a');
+pr
+// CHECK-NEXT: (std::pair<int, char> &) { 42, 'a' }
+
+#include <tuple>
+std::tuple<int,double,char> tu(42,3.14,'a');
+tu
+// CHECK-NEXT: (std::tuple<int, double, char> &) { 42, 3.14000000000, 'a' }
+
+#include <map>
+std::map<const char*, int> m1{{"CPU", 10}, {"GPU", 15}, {"RAM", 20}};
+m1
+// CHECK-NEXT: (std::map<const char *, int> &) { "CPU" => 10, "GPU" => 15, "RAM" => 20 }
+
+#include <unordered_map>
+std::unordered_map<int, int> m2 = { {1,2}, {3,4}};
+m2
+// CHECK-NEXT: (std::unordered_map<int, int> &) { [[Num:[0-9]+]] => [[Num:[0-9]+]], [[Num:[0-9]+]] => [[Num:[0-9]+]] }
+
+struct MyType {};
+std::string PrintValueRuntime(const MyType*) { return "My pretty printer!"; }
+MyType{}
+// CHECK-NEXT: (MyType) My pretty printer!
+%quit
+
diff --git a/clang/tools/clang-repl/CMakeLists.txt b/clang/tools/clang-repl/CMakeLists.txt
index d3dec1984b78d2..2b7d5f01418919 100644
--- a/clang/tools/clang-repl/CMakeLists.txt
+++ b/clang/tools/clang-repl/CMakeLists.txt
@@ -11,6 +11,65 @@ add_clang_tool(clang-repl
   ClangRepl.cpp
   )
 
+if(MSVC)
+  set_target_properties(clang-repl PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS 1)
+
+  # RTTI/C++ symbols
+  set(clang_repl_exports ${clang_repl_exports} ??_7type_info@@6B@
+    ?__type_info_root_node@@3U__type_info_node@@A
+    ?nothrow at std@@3Unothrow_t at 1@B
+  )
+
+  # Compiler added symbols for static variables. NOT for VStudio < 2015
+  set(clang_repl_exports ${clang_repl_exports} _Init_thread_abort _Init_thread_epoch
+    _Init_thread_footer _Init_thread_header _tls_index
+  )
+
+  if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    # new/delete variants needed when linking to static msvc runtime (esp. Debug)
+    set(clang_repl_exports ${clang_repl_exports}
+      ??2 at YAPEAX_K@Z
+      ??3 at YAXPEAX@Z
+      ??_U at YAPEAX_K@Z
+      ??_V at YAXPEAX@Z
+      ??3 at YAXPEAX_K@Z
+      ??6?$basic_ostream at DU?$char_traits at D@std@@@std@@QEAAAEAV01 at H@Z
+      ??6?$basic_ostream at DU?$char_traits at D@std@@@std@@QEAAAEAV01 at M@Z
+      ??6?$basic_ostream at DU?$char_traits at D@std@@@std@@QEAAAEAV01 at N@Z
+      ??6?$basic_ostream at DU?$char_traits at D@std@@@std@@QEAAAEAV01 at PEBX@Z
+      ??6?$basic_ostream at DU?$char_traits at D@std@@@std@@QEAAAEAV01 at P6AAEAV01@AEAV01@@Z at Z
+      ??$?6U?$char_traits at D@std@@@std@@YAAEAV?$basic_ostream at DU?$char_traits at D@std@@@0 at AEAV10@D at Z
+      ??$?6U?$char_traits at D@std@@@std@@YAAEAV?$basic_ostream at DU?$char_traits at D@std@@@0 at AEAV10@PEBD at Z
+      ?_Facet_Register at std@@YAXPEAV_Facet_base at 1@@Z
+    )
+  else()
+    set(clang_repl_exports ${clang_repl_exports}
+      ??2 at YAPAXI@Z
+      ??3 at YAXPAX@Z
+      ??3 at YAXPAXI@Z
+      ??_U at YAPAXI@Z
+      ??_V at YAXPAX@Z
+      ??_V at YAXPAXI@Z
+      ??6?$basic_ostream at DU?$char_traits at D@std@@@std@@QAEAAV01 at H@Z
+      ??6?$basic_ostream at DU?$char_traits at D@std@@@std@@QAEAAV01 at M@Z
+      ??6?$basic_ostream at DU?$char_traits at D@std@@@std@@QAEAAV01 at N@Z
+      ??6?$basic_ostream at DU?$char_traits at D@std@@@std@@QAEAAV01 at PBX@Z
+      ??6?$basic_ostream at DU?$char_traits at D@std@@@std@@QAEAAV01 at P6AAAV01@AAV01@@Z at Z
+      ??$?6U?$char_traits at D@std@@@std@@YAAAV?$basic_ostream at DU?$char_traits at D@std@@@0 at AAV10@D at Z
+      ??$?6U?$char_traits at D@std@@@std@@YAAAV?$basic_ostream at DU?$char_traits at D@std@@@0 at AAV10@PBD at Z
+      ?_Facet_Register at std@@YAXPAV_Facet_base at 1@@Z
+    )
+  endif()
+
+  # List to '/EXPORT:sym0 /EXPORT:sym1 /EXPORT:sym2 ...'
+  foreach(sym ${clang_repl_exports})
+    set(clang_repl_link_str "${clang_repl_link_str} /EXPORT:${sym}")
+  endforeach(sym ${clang_repl_exports})
+
+  set_property(TARGET clang-repl APPEND_STRING PROPERTY LINK_FLAGS ${clang_repl_link_str})
+
+endif(MSVC)
+
 clang_target_link_libraries(clang-repl PRIVATE
   clangAST
   clangBasic
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 5bad8145324d06..edab4a63915336 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -164,7 +164,7 @@ int main(int argc, const char **argv) {
     return 0;
   }
 
-  clang::IncrementalCompilerBuilder CB;
+  clang::caas::IncrementalCompilerBuilder CB;
   CB.SetCompilerArgs(ClangArgv);
 
   std::unique_ptr<clang::CompilerInstance> DeviceCI;
@@ -199,11 +199,10 @@ int main(int argc, const char **argv) {
   if (CudaEnabled)
     DeviceCI->LoadRequestedPlugins();
 
-  std::unique_ptr<clang::Interpreter> Interp;
-
+  std::unique_ptr<clang::caas::Interpreter> Interp;
   if (CudaEnabled) {
-    Interp = ExitOnErr(
-        clang::Interpreter::createWithCUDA(std::move(CI), std::move(DeviceCI)));
+    Interp = ExitOnErr(clang::caas::Interpreter::createWithCUDA(
+        std::move(CI), std::move(DeviceCI)));
 
     if (CudaPath.empty()) {
       ExitOnErr(Interp->LoadDynamicLibrary("libcudart.so"));
@@ -212,7 +211,7 @@ int main(int argc, const char **argv) {
       ExitOnErr(Interp->LoadDynamicLibrary(CudaRuntimeLibPath.c_str()));
     }
   } else
-    Interp = ExitOnErr(clang::Interpreter::create(std::move(CI)));
+    Interp = ExitOnErr(clang::caas::Interpreter::create(std::move(CI)));
 
   for (const std::string &input : OptInputs) {
     if (auto Err = Interp->ParseAndExecute(input))
diff --git a/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp b/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
index 2f1c4efb381f00..be9c5f7c01a517 100644
--- a/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ b/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -38,6 +38,7 @@ LLVM_ATTRIBUTE_USED int __lsan_is_turned_off() { return 1; }
 #endif
 
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 using Args = std::vector<const char *>;
@@ -46,12 +47,12 @@ createInterpreter(const Args &ExtraArgs = {},
                   DiagnosticConsumer *Client = nullptr) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
-  auto CB = clang::IncrementalCompilerBuilder();
+  auto CB = clang::caas::IncrementalCompilerBuilder();
   CB.SetCompilerArgs(ClangArgs);
   auto CI = cantFail(CB.CreateCpp());
   if (Client)
     CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false);
-  return cantFail(clang::Interpreter::create(std::move(CI)));
+  return cantFail(clang::caas::Interpreter::create(std::move(CI)));
 }
 
 TEST(InterpreterTest, CatchException) {
diff --git a/clang/unittests/Interpreter/IncrementalProcessingTest.cpp b/clang/unittests/Interpreter/IncrementalProcessingTest.cpp
index accdf682896340..7f64c5378a21fb 100644
--- a/clang/unittests/Interpreter/IncrementalProcessingTest.cpp
+++ b/clang/unittests/Interpreter/IncrementalProcessingTest.cpp
@@ -27,6 +27,7 @@
 
 using namespace llvm;
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 
@@ -52,12 +53,12 @@ const Function *getGlobalInit(llvm::Module *M) {
 
 TEST(IncrementalProcessing, EmitCXXGlobalInitFunc) {
   std::vector<const char *> ClangArgv = {"-Xclang", "-emit-llvm-only"};
-  auto CB = clang::IncrementalCompilerBuilder();
+  auto CB = clang::caas::IncrementalCompilerBuilder();
   CB.SetCompilerArgs(ClangArgv);
   auto CI = cantFail(CB.CreateCpp());
   auto Interp = llvm::cantFail(Interpreter::create(std::move(CI)));
 
-  std::array<clang::PartialTranslationUnit *, 2> PTUs;
+  std::array<clang::caas::PartialTranslationUnit *, 2> PTUs;
 
   PTUs[0] = &llvm::cantFail(Interp->Parse(TestProgram1));
   ASSERT_TRUE(PTUs[0]->TheModule);
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index e76c0677db5ead..9098eecdfb6c56 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -29,6 +29,7 @@
 #include "gtest/gtest.h"
 
 using namespace clang;
+using namespace caas;
 
 #if defined(_AIX)
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
@@ -46,12 +47,12 @@ createInterpreter(const Args &ExtraArgs = {},
                   DiagnosticConsumer *Client = nullptr) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
-  auto CB = clang::IncrementalCompilerBuilder();
+  auto CB = clang::caas::IncrementalCompilerBuilder();
   CB.SetCompilerArgs(ClangArgs);
   auto CI = cantFail(CB.CreateCpp());
   if (Client)
     CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false);
-  return cantFail(clang::Interpreter::create(std::move(CI)));
+  return cantFail(clang::caas::Interpreter::create(std::move(CI)));
 }
 
 static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {

>From cd22ee8e45d49317d511c954cd646a6e1f232903 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev <v.g.vassilev at gmail.com>
Date: Thu, 20 Jul 2023 19:51:25 +0000
Subject: [PATCH 2/2] Store state

---
 clang/include/clang/AST/ASTContext.h             |  2 ++
 clang/include/clang/Interpreter/Interpreter.h    | 10 ++++++++++
 clang/lib/Interpreter/IncrementalExecutor.cpp    |  4 ----
 clang/lib/Interpreter/IncrementalExecutor.h      |  1 -
 clang/lib/Interpreter/Interpreter.cpp            | 16 ----------------
 clang/lib/Interpreter/InterpreterUtils.cpp       |  2 +-
 clang/lib/Interpreter/ValuePrinter.cpp           | 15 ++++++++++-----
 clang/tools/clang-repl/ClangRepl.cpp             | 10 +++++-----
 .../unittests/Interpreter/CodeCompletionTest.cpp | 10 +++++-----
 9 files changed, 33 insertions(+), 37 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index ff6b64c7f72d57..44ee6510251230 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1066,6 +1066,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
   Module *getCurrentNamedModule() const { return CurrentCXXNamedModule; }
 
   TranslationUnitDecl *getTranslationUnitDecl() const {
+    assert(TUDecl->getMostRecentDecl() == TUDecl &&
+           "The active TU is not current one!");
     return TUDecl->getMostRecentDecl();
   }
   void addTranslationUnitDecl() {
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 10ae4ce1de06bb..d9972ab8c7298d 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -94,6 +94,14 @@ class Interpreter {
   Value LastValue;
 
 public:
+  class SynthesizingCodeRAII {
+
+  };
+
+  SynthesizingCodeRAII EnterCodeSynthesisScope() {
+
+  }
+
   ~Interpreter();
   static llvm::Expected<std::unique_ptr<Interpreter>>
   create(std::unique_ptr<CompilerInstance> CI);
@@ -142,6 +150,8 @@ class Interpreter {
 
   std::unique_ptr<llvm::Module> GenModule();
 
+  
+
 private:
   size_t getEffectivePTUSize() const;
 
diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp
index 1e8fdcfef049ca..1a6e81f489d462 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.cpp
+++ b/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -65,10 +65,6 @@ IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
 
 IncrementalExecutor::~IncrementalExecutor() {}
 
-llvm::Error IncrementalExecutor::addModule(std::unique_ptr<llvm::Module> &M) {
-  return Jit->addIRModule({std::move(M), TSCtx});
-}
-
 llvm::Error IncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
   llvm::orc::ResourceTrackerSP RT =
       Jit->getMainJITDylib().createResourceTracker();
diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h
index f1ea27f7d3031b..33d42852f423df 100644
--- a/clang/lib/Interpreter/IncrementalExecutor.h
+++ b/clang/lib/Interpreter/IncrementalExecutor.h
@@ -50,7 +50,6 @@ class IncrementalExecutor {
                       const clang::TargetInfo &TI);
   ~IncrementalExecutor();
 
-  llvm::Error addModule(std::unique_ptr<llvm::Module> &M);
   llvm::Error addModule(PartialTranslationUnit &PTU);
   llvm::Error removeModule(PartialTranslationUnit &PTU);
   llvm::Error runCtors() const;
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index ef60a3f1e46efb..98679c89edc1f4 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -378,22 +378,6 @@ llvm::Error Interpreter::CreateExecutor() {
   return Err;
 }
 
-llvm::Error Interpreter::ExecuteModule(std::unique_ptr<llvm::Module> &M) {
-  if (!IncrExecutor) {
-    auto Err = CreateExecutor();
-    if (Err)
-      return Err;
-  }
-  // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
-  if (auto Err = IncrExecutor->addModule(M))
-    return Err;
-
-  if (auto Err = IncrExecutor->runCtors())
-    return Err;
-
-  return llvm::Error::success();
-}
-
 llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
   assert(T.TheModule);
   if (!IncrExecutor) {
diff --git a/clang/lib/Interpreter/InterpreterUtils.cpp b/clang/lib/Interpreter/InterpreterUtils.cpp
index 3772b292ede52b..0a33116eefd5e1 100644
--- a/clang/lib/Interpreter/InterpreterUtils.cpp
+++ b/clang/lib/Interpreter/InterpreterUtils.cpp
@@ -484,7 +484,7 @@ QualType GetFullyQualifiedType(QualType QT, const ASTContext &Ctx) {
   if (Prefix) {
     // We intentionally always use ETK_None, we never want
     // the keyword (humm ... what about anonymous types?)
-    QT = Ctx.getElaboratedType(ETK_None, Prefix, QT);
+    QT = Ctx.getElaboratedType(ElaboratedTypeKeyword::None, Prefix, QT);
     QT = Ctx.getQualifiedType(QT, PrefixQualifiers);
   }
   return QT;
diff --git a/clang/lib/Interpreter/ValuePrinter.cpp b/clang/lib/Interpreter/ValuePrinter.cpp
index a80a1960d05780..3f8c9a6f26cbbf 100644
--- a/clang/lib/Interpreter/ValuePrinter.cpp
+++ b/clang/lib/Interpreter/ValuePrinter.cpp
@@ -115,9 +115,9 @@ static std::string PrintEnum(const Value &V) {
       IsFirst = false;
     }
   }
-
-  SS << " : " << PrintQualType(Ctx, ED->getIntegerType()) << " "
-     << llvm::toString(AP, /*Radix=*/10);
+  llvm::SmallString<64> APStr;
+  AP.toString(APStr, /*Radix=*/10);
+  SS << " : " << PrintQualType(Ctx, ED->getIntegerType()) << " "  << APStr;
   return Str;
 }
 
@@ -277,10 +277,15 @@ static llvm::Expected<llvm::orc::ExecutorAddr> CompileDecl(Interpreter &Interp,
   ASTConsumer &Consumer = Interp.getCompilerInstance()->getASTConsumer();
   Consumer.HandleTopLevelDecl(DeclGroupRef(D));
   Interp.getCompilerInstance()->getSema().PerformPendingInstantiations();
-  Consumer.HandleTranslationUnit(Interp.getASTContext());
+  ASTContext &C = Interp.getASTContext();
+  TranslationUnitDecl *TUPart = C.getTranslationUnitDecl();
+  assert(!TUPart->containsDecl(D) && "Decl already added!");
+  TUPart->addDecl(D);
+  Consumer.HandleTranslationUnit(C);
 
   if (std::unique_ptr<llvm::Module> M = Interp.GenModule()) {
-    if (llvm::Error Err = Interp.ExecuteModule(M))
+    PartialTranslationUnit PTU = {TUPart, std::move(M)};
+    if (llvm::Error Err = Interp.Execute(PTU))
       return Err;
     ASTNameGenerator ASTNameGen(Interp.getASTContext());
     llvm::Expected<llvm::orc::ExecutorAddr> AddrOrErr =
diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index edab4a63915336..640d3a1518e47e 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -82,10 +82,10 @@ static int checkDiagErrors(const clang::CompilerInstance *CI, bool HasError) {
 }
 
 struct ReplListCompleter {
-  clang::IncrementalCompilerBuilder &CB;
-  clang::Interpreter &MainInterp;
-  ReplListCompleter(clang::IncrementalCompilerBuilder &CB,
-                    clang::Interpreter &Interp)
+  clang::caas::IncrementalCompilerBuilder &CB;
+  clang::caas::Interpreter &MainInterp;
+  ReplListCompleter(clang::caas::IncrementalCompilerBuilder &CB,
+                    clang::caas::Interpreter &Interp)
       : CB(CB), MainInterp(Interp){};
 
   std::vector<llvm::LineEditor::Completion> operator()(llvm::StringRef Buffer,
@@ -117,7 +117,7 @@ ReplListCompleter::operator()(llvm::StringRef Buffer, size_t Pos,
 
   size_t Lines =
       std::count(Buffer.begin(), std::next(Buffer.begin(), Pos), '\n') + 1;
-  auto Interp = clang::Interpreter::create(std::move(*CI));
+  auto Interp = clang::caas::Interpreter::create(std::move(*CI));
 
   if (auto Err = Interp.takeError()) {
     // log the error and returns an empty vector;
diff --git a/clang/unittests/Interpreter/CodeCompletionTest.cpp b/clang/unittests/Interpreter/CodeCompletionTest.cpp
index 873fbda32f0579..6f18061da6910e 100644
--- a/clang/unittests/Interpreter/CodeCompletionTest.cpp
+++ b/clang/unittests/Interpreter/CodeCompletionTest.cpp
@@ -13,14 +13,14 @@
 
 using namespace clang;
 namespace {
-auto CB = clang::IncrementalCompilerBuilder();
+auto CB = clang::caas::IncrementalCompilerBuilder();
 
-static std::unique_ptr<Interpreter> createInterpreter() {
+static std::unique_ptr<caas::Interpreter> createInterpreter() {
   auto CI = cantFail(CB.CreateCpp());
-  return cantFail(clang::Interpreter::create(std::move(CI)));
+  return cantFail(caas::Interpreter::create(std::move(CI)));
 }
 
-static std::vector<std::string> runComp(clang::Interpreter &MainInterp,
+static std::vector<std::string> runComp(caas::Interpreter &MainInterp,
                                         llvm::StringRef Input,
                                         llvm::Error &ErrR) {
   auto CI = CB.CreateCpp();
@@ -29,7 +29,7 @@ static std::vector<std::string> runComp(clang::Interpreter &MainInterp,
     return {};
   }
 
-  auto Interp = clang::Interpreter::create(std::move(*CI));
+  auto Interp = caas::Interpreter::create(std::move(*CI));
   if (auto Err = Interp.takeError()) {
     // log the error and returns an empty vector;
     ErrR = std::move(Err);



More information about the cfe-commits mailing list