junaire updated this revision to Diff 501360.
junaire added a comment.

Support printing temporaries.

Note there's a ugly hack because I didn't find the right way to synthesize
the AST for explicit destructor call.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141215/new/

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/Value.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/tools/clang-repl/ClangRepl.cpp

Index: clang/tools/clang-repl/ClangRepl.cpp
===================================================================
--- clang/tools/clang-repl/ClangRepl.cpp
+++ clang/tools/clang-repl/ClangRepl.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/AST/Decl.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
@@ -18,6 +19,8 @@
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/LineEditor/LineEditor.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ManagedStatic.h" // llvm_shutdown
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/TargetSelect.h" // llvm::Initialize*
@@ -66,6 +69,32 @@
   return (Errs || HasError) ? EXIT_FAILURE : EXIT_SUCCESS;
 }
 
+static void DeclareMagicFunctions(clang::Interpreter &Interp) {
+  std::vector<llvm::StringRef> MagicFunctions = {
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, bool);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, char);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, signed char);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, short);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, int);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, long);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, long long);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned char);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned short);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned int);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long "
+      "long);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, float);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, double);",
+      "void __InterpreterSetValueNoAlloc(void*, void*, void*, void*);",
+      "void* __InterpreterSetValueWithAlloc(void*, void*, void*);"};
+
+  for (llvm::StringRef Function : MagicFunctions) {
+    llvm::cantFail(Interp.ParseAndExecute(Function));
+  }
+  llvm::cantFail(Interp.ParseAndExecute("#include <new>"));
+}
+
 llvm::ExitOnError ExitOnErr;
 int main(int argc, const char **argv) {
   ExitOnErr.setBanner("clang-repl: ");
@@ -110,6 +139,7 @@
 
   bool HasError = false;
 
+  DeclareMagicFunctions(*Interp);
   if (OptInputs.empty()) {
     llvm::LineEditor LE("clang-repl");
     // FIXME: Add LE.setListCompleter
Index: clang/tools/clang-repl/CMakeLists.txt
===================================================================
--- clang/tools/clang-repl/CMakeLists.txt
+++ clang/tools/clang-repl/CMakeLists.txt
@@ -12,6 +12,7 @@
   )
 
 clang_target_link_libraries(clang-repl PRIVATE
+  clangAST
   clangBasic
   clangFrontend
   clangInterpreter
Index: clang/test/Interpreter/pretty-print.cpp
===================================================================
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,23 @@
+// 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 | FileCheck %s
+char c = 'a';
+c
+// CHECK: (char) a
+
+int x = 42;
+x
+// CHECK-NEXT: (int) 42
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.21
+
+%quit
+
Index: clang/lib/Parse/Parser.cpp
===================================================================
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -154,10 +154,20 @@
   return true;
 }
 
-bool Parser::ExpectAndConsumeSemi(unsigned DiagID, StringRef TokenUsed) {
+bool Parser::ExpectAndConsumeSemi(unsigned DiagID, StringRef TokenUsed,
+                                  bool IsTopExpr) {
   if (TryConsumeToken(tok::semi))
     return false;
 
+  // If this is in the incremental C++ mode, then it means we need to pretty
+  // print this expression. Thus, let's pretend we have this semi and continue
+  // parsing.
+  if (PP.isIncrementalProcessingEnabled() && IsTopExpr &&
+      DiagID == diag::err_expected_semi_after_expr) {
+    setPrettyPrintMode();
+    return false;
+  }
+
   if (Tok.is(tok::code_completion)) {
     handleUnexpectedCodeCompletionToken();
     return false;
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -542,9 +542,9 @@
     // Recover parsing as a case statement.
     return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
   }
-
   // Otherwise, eat the semicolon.
-  ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+  ExpectAndConsumeSemi(diag::err_expected_semi_after_expr, /*TokenUsed=*/"",
+                       StmtCtx == ParsedStmtContext::SubStmt);
   return handleExprStmt(Expr, StmtCtx);
 }
 
Index: clang/lib/Interpreter/Value.cpp
===================================================================
--- /dev/null
+++ clang/lib/Interpreter/Value.cpp
@@ -0,0 +1,172 @@
+#include "clang/Interpreter/Value.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/Interpreter/Interpreter.h"
+#include "llvm/Support/raw_os_ostream.h"
+#include <cassert>
+#include <utility>
+
+using namespace clang;
+
+namespace {
+
+// This is internal buffer maintained by Value, used to hold temporaries.
+class ValueStorage {
+public:
+  using DtorFunc = void (*)(void *);
+
+  static unsigned char *CreatePayload(void *DtorF, size_t AllocSize,
+                                      size_t ElementsSize) {
+    unsigned char *Buf = new unsigned char[1024];
+    ValueStorage *VS = new (Buf) ValueStorage(DtorF, AllocSize, ElementsSize);
+    return VS->getPayload();
+  }
+
+  unsigned char *getPayload() { return Storage; }
+  const unsigned char *getPayload() const { return Storage; }
+
+  static unsigned getPayloadOffset() {
+    static ValueStorage Dummy(nullptr, 0, 0);
+    return Dummy.getPayload() - reinterpret_cast<unsigned char *>(&Dummy);
+  }
+
+  static ValueStorage *getFromPayload(void *Payload) {
+    return reinterpret_cast<ValueStorage *>((unsigned char *)Payload -
+                                            getPayloadOffset());
+  }
+
+  void Retain() { ++RefCnt; }
+
+  void Release() {
+    assert(RefCnt == 0 && "Can't release if reference count is already zero");
+    if (--RefCnt == 0) {
+      // We hace a non-trivial dtor.
+      if (Dtor) {
+        size_t Stride = AllocSize / Elements;
+        for (size_t Idx = 0; Idx < Elements; ++Idx)
+          (*Dtor)(getPayload() + Idx * Stride);
+      }
+      delete[] reinterpret_cast<unsigned char *>(this);
+    }
+  }
+
+private:
+  ValueStorage(void *DtorF, size_t AllocSize, size_t ElementsNum)
+      : RefCnt(1), AllocSize(AllocSize), Elements(ElementsNum),
+        Dtor(reinterpret_cast<DtorFunc>(DtorF)) {}
+
+  mutable unsigned RefCnt;
+  size_t AllocSize = 0;
+  size_t Elements = 0;
+  unsigned char Storage[1];
+  DtorFunc Dtor = nullptr;
+};
+} // namespace
+
+Value::Value(void *In, void *Ty, Kind K)
+    : Interp(In), OpaqueType(Ty), ValueKind(K) {
+  if (ValueKind == K_PtrOrObj) {
+    QualType Canon = getType().getCanonicalType();
+    if ((Canon->isPointerType() || Canon->isObjectType() ||
+         Canon->isReferenceType()) &&
+        (Canon->isRecordType() || Canon->isConstantArrayType() ||
+         Canon->isMemberPointerType())) {
+      // Compile dtor function.
+      Interpreter &Interp = getInterpreter();
+      void *DtorF = nullptr;
+      // FIXME: Arrays
+      if (const auto *RT = getType()->getAs<RecordType>())
+        // FIXME: How to handle errors in a constructor?
+        DtorF = llvm::cantFail(Interp.CompileDtorCall(RT->getDecl()));
+
+      size_t AllocSize =
+          getASTContext().getTypeSizeInChars(getType()).getQuantity();
+      size_t ElementsSize = 1;
+      setPtr(ValueStorage::CreatePayload(DtorF, AllocSize, ElementsSize));
+    }
+  }
+}
+
+Value::Value(const Value &RHS)
+    : Interp(RHS.Interp), OpaqueType(RHS.OpaqueType), ValueKind(RHS.ValueKind),
+      IsManuallyAlloc(RHS.IsManuallyAlloc) {
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Retain();
+}
+
+Value::Value(Value &&RHS) noexcept {
+  Interp = std::exchange(RHS.Interp, nullptr);
+  OpaqueType = std::exchange(RHS.Interp, nullptr);
+  ValueKind = std::exchange(RHS.ValueKind, K_Unspecified);
+
+  IsManuallyAlloc = RHS.IsManuallyAlloc;
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Release();
+}
+
+Value &Value::operator=(const Value &RHS) {
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Release();
+
+  Interp = RHS.Interp;
+  OpaqueType = RHS.Interp;
+  ValueKind = RHS.ValueKind;
+  IsManuallyAlloc = RHS.IsManuallyAlloc;
+
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Retain();
+
+  return *this;
+}
+
+Value &Value::operator=(Value &&RHS) noexcept {
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Release();
+
+  Interp = std::exchange(RHS.Interp, nullptr);
+  OpaqueType = std::exchange(RHS.OpaqueType, nullptr);
+  ValueKind = std::exchange(RHS.ValueKind, K_Unspecified);
+  IsManuallyAlloc = RHS.IsManuallyAlloc;
+
+  return *this;
+}
+
+Value::~Value() {
+  if (IsManuallyAlloc)
+    ValueStorage::getFromPayload(getPtr())->Release();
+}
+
+QualType Value::getType() const {
+  return QualType::getFromOpaquePtr(OpaqueType);
+}
+
+Interpreter &Value::getInterpreter() {
+  assert(Interp != nullptr &&
+         "Can't get interpreter from a default constructed value");
+  return *reinterpret_cast<Interpreter *>(Interp);
+}
+
+ASTContext &Value::getASTContext() { return getInterpreter().getASTContext(); }
+
+void Value::print(llvm::raw_ostream &Out) const {
+  assert(OpaqueType != nullptr && "Can't print default Value");
+  Out << "(" << getType().getAsString() << ") ";
+  switch (getKind()) {
+  case K_Unspecified:
+    assert(false);
+  case K_Void:
+    Out << " \n";
+    break;
+  case K_PtrOrObj:
+    Out << getPtr() << "\n";
+    break;
+#define X(type, name)                                                          \
+  case K_##name:                                                               \
+    Out << get##name() << "\n";                                                \
+    break;
+    BUILTIN_TYPES
+#undef X
+  }
+}
+
+void Value::dump() const { print(llvm::outs()); }
Index: clang/lib/Interpreter/Interpreter.cpp
===================================================================
--- clang/lib/Interpreter/Interpreter.cpp
+++ clang/lib/Interpreter/Interpreter.cpp
@@ -15,8 +15,20 @@
 
 #include "IncrementalExecutor.h"
 #include "IncrementalParser.h"
-
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Mangle.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
@@ -27,11 +39,22 @@
 #include "clang/Driver/Tool.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Interpreter/PartialTranslationUnit.h"
 #include "clang/Lex/PreprocessorOptions.h"
-
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/TargetParser/Host.h"
+#include <cassert>
 
 using namespace clang;
 
@@ -199,6 +222,10 @@
   return std::move(Interp);
 }
 
+ASTContext &Interpreter::getASTContext() const {
+  return getCompilerInstance()->getASTContext();
+}
+
 const CompilerInstance *Interpreter::getCompilerInstance() const {
   return IncrParser->getCI();
 }
@@ -235,6 +262,31 @@
   return llvm::Error::success();
 }
 
+llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
+  auto PTU = Parse(Code);
+  if (!PTU)
+    return PTU.takeError();
+  if (IncrParser->isPrettyPrintMode()) {
+    IncrParser->setPrettyPrintMode(false);
+
+    // The user ask for a value, return it directly.
+    if (V)
+      if (llvm::Error Err = GenerateValue(*PTU->TUPart, V))
+        return Err;
+
+    // Presumbly we need to perform pretty print.
+    Value DefaultValue;
+    if (llvm::Error Err = GenerateValue(*PTU->TUPart, &DefaultValue))
+      return Err;
+    DefaultValue.dump();
+    return llvm::Error::success();
+  }
+
+  if (PTU->TheModule)
+    return Execute(*PTU);
+  return llvm::Error::success();
+}
+
 llvm::Expected<llvm::JITTargetAddress>
 Interpreter::getSymbolAddress(GlobalDecl GD) const {
   if (!IncrExecutor)
@@ -283,3 +335,412 @@
   }
   return llvm::Error::success();
 }
+
+static IntegerLiteral *IntegerLiteralExpr(ASTContext &C, uintptr_t Ptr) {
+  const llvm::APInt Addr(8 * sizeof(void *), Ptr);
+  return IntegerLiteral::Create(C, Addr, C.getUIntPtrType(), SourceLocation());
+}
+
+static Expr *CStyleCastPtrExpr(Sema &S, QualType Ty, Expr *E) {
+  ASTContext &Ctx = S.getASTContext();
+  if (!Ty->isPointerType())
+    Ty = Ctx.getPointerType(Ty);
+
+  TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
+  Expr *Result =
+      S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E).get();
+  assert(Result && "Cannot create CStyleCastPtrExpr");
+  return Result;
+}
+
+static Expr *CStyleCastPtrExpr(Sema &S, QualType Ty, uintptr_t Ptr) {
+  ASTContext &Ctx = S.getASTContext();
+  return CStyleCastPtrExpr(S, Ty, IntegerLiteralExpr(Ctx, Ptr));
+}
+
+static Sema::DeclGroupPtrTy CreateDGPtrFrom(Sema &S, Decl *D) {
+  SmallVector<Decl *, 1> DeclsInGroup;
+  DeclsInGroup.push_back(D);
+  Sema::DeclGroupPtrTy DeclGroupPtr = S.BuildDeclaratorGroup(DeclsInGroup);
+  return DeclGroupPtr;
+}
+
+static std::string GetUniqueName(std::string Base) {
+  static int I = 0;
+  Base += std::to_string(I);
+  I += 1;
+  return Base;
+}
+
+llvm::Error Interpreter::GenerateValue(TranslationUnitDecl &TU, Value *V) {
+  // Capture the expression we want to print.
+  auto ExprOrErr = CaptureExpr(TU);
+  if (!ExprOrErr)
+    return ExprOrErr.takeError();
+  // Generate a PartialTranslationUnit.
+  std::pair<llvm::Expected<clang::PartialTranslationUnit &>, FunctionDecl *>
+      SynthesizedPTUOrErr = SynthesizePTU(*ExprOrErr);
+  if (!SynthesizedPTUOrErr.first)
+    return SynthesizedPTUOrErr.first.takeError();
+
+  if (SynthesizedPTUOrErr.first->TheModule)
+    if (llvm::Error Err = Execute(*SynthesizedPTUOrErr.first))
+      return Err;
+
+  ASTNameGenerator ASTNameGen(getCompilerInstance()->getASTContext());
+  llvm::Expected<llvm::JITTargetAddress> AddrOrErr =
+      getSymbolAddressFromLinkerName(
+          ASTNameGen.getName(SynthesizedPTUOrErr.second));
+  if (!AddrOrErr)
+    return AddrOrErr.takeError();
+
+  if (auto *Main = llvm::jitTargetAddressToPointer<void (*)(void *, void *)>(
+          AddrOrErr.get()))
+    (*Main)((void *)this, (void *)V);
+  return llvm::Error::success();
+}
+
+static std::string GetTypeName(ASTContext& Ctx, QualType QT) {
+  PrintingPolicy Policy(Ctx.getPrintingPolicy());
+  Policy.SuppressScope = false;
+  Policy.AnonymousTagLocations = false;
+  return QT.getAsString(Policy);
+}
+
+// Capture the last expression in the interpreter. We assume the user only
+// inputted a top level statement.
+llvm::Expected<Expr *> Interpreter::CaptureExpr(TranslationUnitDecl &TU) {
+  assert(std::distance(TU.decls_begin(), TU.decls_end()) > 0 &&
+         "Cannot capture Expr* in empty TranslationUnitDecl");
+
+  auto Size = std::distance(TU.decls_begin(), TU.decls_end());
+  auto Last = TU.decls_begin();
+  while (Size-- != 1)
+    Last++;
+
+  if (const auto *S = llvm::dyn_cast<clang::TopLevelStmtDecl>(*Last))
+    if (const auto *E = llvm::dyn_cast<clang::Expr>(S->getStmt()))
+      return const_cast<Expr *>(E);
+
+  return llvm::make_error<llvm::StringError>("Can not capture any Expr*!",
+                                             std::error_code());
+}
+llvm::Expected<void *> Interpreter::CompileDtorCall(const RecordDecl *RD) {
+  if (auto Dtor = Dtors.find(RD); Dtor != Dtors.end())
+    return Dtor->getSecond();
+
+  // No need to generate the destructor if it has no semantic effects.
+  if (const CXXRecordDecl *CXXRD = llvm::dyn_cast<CXXRecordDecl>(RD);
+      CXXRD->hasIrrelevantDestructor())
+    return nullptr;
+
+  // Generate AST.
+  //
+  // extern "C" void __InterpreterDtorT(void* obj) {
+  //   ((T*)obj)->~T();
+  // }
+  //
+  QualType QT(RD->getTypeForDecl(), 0);
+
+  std::string TypeName = GetTypeName(getCompilerInstance()->getASTContext(), QT);
+
+  const char *CodeTemplate = R"(
+    extern "C" void __InterpreterDtor{0}(void* obj) {
+      (({0}*)obj)->~{0}();
+    }
+  )";
+  std::string Code = llvm::formatv(CodeTemplate, TypeName);
+  std::string DtorName = llvm::formatv("__InterpreterDtor{0}", TypeName);
+  llvm::Expected<PartialTranslationUnit &> PTUOrErr = Parse(Code);
+  // FIXME: Can't we just synthesize the AST directly?
+#if 0
+  Sema &S = getCompilerInstance()->getSema();
+  ASTContext &Ctx = S.getASTContext();
+
+  QualType QT(RD->getTypeForDecl(), 0);
+  std::string DtorName = "__InterpreterDtor" + QT.getAsString();
+
+  QualType RetTy = Ctx.VoidTy;
+  QualType ArgTy = Ctx.VoidPtrTy;
+
+  QualType FunctionTy = Ctx.getFunctionType(RetTy, {ArgTy}, {});
+  IdentifierInfo *II = &Ctx.Idents.get(DtorName);
+  // Extern "C" ?
+  auto *FD = FunctionDecl::Create(
+      S.getASTContext(), Ctx.getTranslationUnitDecl(), SourceLocation(),
+      SourceLocation(), II, FunctionTy, /*TInfo=*/nullptr, SC_Extern);
+  auto *ObjParm = ParmVarDecl::Create(
+      Ctx, FD, SourceLocation(), SourceLocation(), /*Id=*/nullptr, ArgTy,
+      Ctx.getTrivialTypeSourceInfo(ArgTy, SourceLocation()), SC_None,
+      /*DefArg=*/nullptr);
+  FD->setParams({ObjParm});
+
+  // The function Body.
+  auto *Obj = DeclRefExpr::Create(Ctx, NestedNameSpecifierLoc(),
+                                  SourceLocation(), ObjParm,
+                                  /*RefersToEnclosingVariableOrCapture=*/false,
+                                  SourceLocation(), ArgTy, VK_PRValue);
+  // Force cast it to the right type.
+  Expr *CastedExpr = CStyleCastPtrExpr(S, QT, Obj);
+
+  ExprResult DtorCall = nullptr;
+
+  assert(!DtorCall.isInvalid() && "Can't create the destructor call!");
+
+  FD->setBody(DtorCall.get());
+  // Compile it.
+  llvm::Expected<PartialTranslationUnit &> PTUOrErr =
+      IncrParser->Parse(CreateDGPtrFrom(S, FD));
+#endif
+  if (!PTUOrErr)
+    return PTUOrErr.takeError();
+  if (PTUOrErr->TheModule)
+    if (llvm::Error Err = Execute(*PTUOrErr))
+      return Err;
+
+  // Look up the function address in the JIT.
+  if (llvm::Expected<llvm::JITTargetAddress> AddrOrErr =
+          getSymbolAddressFromLinkerName(DtorName)) {
+    void *Dtor = (void *)*AddrOrErr;
+    Dtors[RD] = Dtor;
+    return Dtor;
+  }
+  return nullptr;
+}
+
+static constexpr llvm::StringRef MagicRuntimeInterface[] = {
+    "__InterpreterSetValueNoAlloc", "__InterpreterSetValueWithAlloc"};
+
+bool Interpreter::FindRuntimeInterface() {
+  if (RuntimeAllocInterface && RuntimeNoAllocInterface)
+    return true;
+
+  Sema &S = getCompilerInstance()->getSema();
+  ASTContext &Ctx = S.getASTContext();
+
+  auto LookupInterface = [&](Expr *&Interface, llvm::StringRef Name) {
+    LookupResult R(S, &Ctx.Idents.get(Name), SourceLocation(),
+                   Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration);
+    S.LookupQualifiedName(R, Ctx.getTranslationUnitDecl());
+    if (R.empty())
+      return false;
+
+    CXXScopeSpec CSS;
+    Interface = S.BuildDeclarationNameExpr(CSS, R, /*ADL=*/false).get();
+    return true;
+  };
+
+  if (!LookupInterface(RuntimeNoAllocInterface, MagicRuntimeInterface[0]))
+    return false;
+  if (!LookupInterface(RuntimeAllocInterface, MagicRuntimeInterface[1]))
+    return false;
+  return true;
+}
+
+namespace {
+
+class RuntimeInterfaceBuilder
+    : public TypeVisitor<RuntimeInterfaceBuilder, bool> {
+  clang::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)
+      : Interp(In), Ctx(C), S(SemaRef), E(VE) {
+    // The Interpreter* parameter and the out parameter `OutVal`.
+    for (Expr *E : FixedArgs)
+      Args.push_back(E);
+
+    // Get rid of ExprWithCleanups.
+    if (auto *EWC = llvm::dyn_cast_if_present<ExprWithCleanups>(E))
+      E = EWC->getSubExpr();
+  }
+
+  ExprResult getCall() {
+    QualType Ty = E->getType();
+    Expr *TypeArg =
+        CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr());
+    // The QualType parameter `OpaqueType`, represented as `void*`.
+    Args.push_back(TypeArg);
+
+    QualType DesugaredTy = Ty.getDesugaredType(Ctx);
+    // For lvalue struct, we treat it as a reference.
+    if (DesugaredTy->isRecordType() && E->isLValue()) {
+      DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy);
+      Ty = Ctx.getLValueReferenceType(Ty);
+    }
+
+    // We push the last parameter based on the type of the Expr. Note we need
+    // special care for rvalue struct.
+    if (Visit(&*DesugaredTy)) {
+      ExprResult AllocCall =
+          S.ActOnCallExpr(/*Scope=*/nullptr, Interp.RuntimeAllocInterface,
+                          E->getBeginLoc(), Args, E->getEndLoc());
+      assert(!AllocCall.isInvalid() && "Can't create runtime interface call!");
+
+      TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
+
+      Expr *Args2[] = {AllocCall.get()};
+
+      ExprResult CXXNewCall = S.BuildCXXNew(
+          E->getSourceRange(),
+          /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args2,
+          /*PlacementRParen=*/SourceLocation(), /*TypeIdParens=*/SourceRange(),
+          TSI->getType(), TSI, std::nullopt, E->getSourceRange(), E);
+
+      assert(!CXXNewCall.isInvalid() &&
+             "Can't create runtime placement new call!");
+
+      return S.ActOnFinishFullExpr(CXXNewCall.get(), /*DiscardedValue=*/false);
+    }
+
+    return S.ActOnCallExpr(/*Scope=*/nullptr, Interp.RuntimeNoAllocInterface,
+                           E->getBeginLoc(), Args, E->getEndLoc());
+  }
+
+  bool VisitRecordType(const RecordType *Ty) { return true; }
+
+  bool VisitMemberPointerType(const MemberPointerType *Ty) {
+    llvm_unreachable("Not implemented yet");
+  }
+  bool VisitConstantArrayType(const ConstantArrayType *Ty) {
+    llvm_unreachable("Not implemented yet");
+  }
+
+  bool VisitPointerType(const PointerType *Ty) {
+    TypeSourceInfo *TSI =
+        Ctx.getTrivialTypeSourceInfo(Ctx.VoidPtrTy, SourceLocation());
+    ExprResult CastedExpr =
+        S.BuildCStyleCastExpr(SourceLocation(), TSI, SourceLocation(), E);
+    assert(!CastedExpr.isInvalid() && "Can not create cstyle cast expression");
+    Args.push_back(CastedExpr.get());
+    return false;
+  }
+
+  bool VisitReferenceType(const ReferenceType *Ty) {
+    ExprResult AddrOfE = S.CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, E);
+    assert(!AddrOfE.isInvalid() && "Can not create unary expression");
+    Args.push_back(AddrOfE.get());
+    return false;
+  }
+
+  bool VisitBuiltinType(const BuiltinType *Ty) {
+    if (Ty->isNullPtrType())
+      Args.push_back(E);
+    else if (Ty->isFloatingType())
+      Args.push_back(E);
+    else if (Ty->isVoidType()) {
+      llvm_unreachable("Not implemented yet");
+    } else if (Ty->isIntegralOrEnumerationType()) {
+      // If we want to reduce the number of the overloads, we should cast it to
+      // uint64.
+      Args.push_back(E);
+    }
+    return false;
+  }
+};
+} // namespace
+
+static constexpr const char *const ValueGetter = "__InterpreterValueGetter";
+
+// This synthesizes a wrapper function that used in passing the Value object to
+// the interpreter. Inside the wrapper we synthesize another call to a speciall
+// function that is responsible for generating the Value.
+// In general, we transform:
+//   clang-repl> x
+// To:
+// void __InterpreterValueGetter(void* ThisInterp, void* OpaqueValue) {
+//   // 1. If x is a built-in type like int, float.
+//   __InterpreterSetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, x);
+//   // 2. If x is a struct, and a lvalue.
+//   __InterpreterSetValueNoAlloc(ThisInterp, OpaqueValue, xQualType, &x);
+//   // 3. If x is a struct, but a rvalue.
+//   new (__InterpreterSetValueWithAlloc(ThisInterp, OpaqueValue, xQualType))
+//   (x);
+// }
+std::pair<llvm::Expected<PartialTranslationUnit &>, FunctionDecl *>
+Interpreter::SynthesizePTU(clang::Expr *E) {
+  Sema &S = getCompilerInstance()->getSema();
+  ASTContext &Ctx = S.getASTContext();
+
+  QualType Void = Ctx.VoidTy;
+  QualType VoidPtr = Ctx.VoidPtrTy;
+
+  // Synthesize function `__InterpreterValueGetter`.
+  QualType FunctionTy = Ctx.getFunctionType(Void, {VoidPtr, VoidPtr}, {});
+  IdentifierInfo *II = &Ctx.Idents.get(GetUniqueName(ValueGetter));
+  auto *FD = FunctionDecl::Create(
+      S.getASTContext(), Ctx.getTranslationUnitDecl(), SourceLocation(),
+      SourceLocation(), II, FunctionTy, /*TInfo=*/nullptr, SC_None);
+
+  // The two parameters:
+  //   1. void* OpaqueInterp
+  //   2. void* OpaqueValue
+  auto *OpaqueInterp = ParmVarDecl::Create(
+      Ctx, FD, SourceLocation(), SourceLocation(), /*Id=*/nullptr, VoidPtr,
+      Ctx.getTrivialTypeSourceInfo(VoidPtr, SourceLocation()), SC_None,
+      /*DefArg=*/nullptr);
+  auto *OpaqueValue = ParmVarDecl::Create(
+      Ctx, FD, SourceLocation(), SourceLocation(), /*Id=*/nullptr, VoidPtr,
+      Ctx.getTrivialTypeSourceInfo(VoidPtr, SourceLocation()), SC_None,
+      /*DefArg=*/nullptr);
+  FD->setParams({OpaqueInterp, OpaqueValue});
+
+  if (!FindRuntimeInterface())
+    llvm_unreachable("We can't find the runtime iterface for pretty print!");
+
+  // Create parameter `ThisInterp` for `__InterpreterSetValue*`
+  auto *ThisInterp = DeclRefExpr::Create(
+      Ctx, NestedNameSpecifierLoc(), SourceLocation(), OpaqueInterp,
+      /*RefersToEnclosingVariableOrCapture=*/false, SourceLocation(),
+      Ctx.VoidPtrTy, VK_PRValue);
+
+  // Create parameter `OutVal` for `__InterpreterSetValue*`
+  auto *OutValue = DeclRefExpr::Create(
+      Ctx, NestedNameSpecifierLoc(), SourceLocation(), OpaqueValue,
+      /*RefersToEnclosingVariableOrCapture=*/false, SourceLocation(),
+      Ctx.VoidPtrTy, VK_PRValue);
+
+  // Build `__InterpreterSetValue*` call.
+  RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue});
+
+  ExprResult Result = Builder.getCall();
+  assert(!Result.isInvalid() && "Failed to generate the CallExpr!");
+  FD->setBody(Result.get());
+
+  // Feed the generated AST to the parser.
+  return {IncrParser->Parse(CreateDGPtrFrom(S, FD)), FD};
+}
+
+// Temporary rvalue struct that need special care.
+void *REPL_EXTERNAL_VISIBILITY
+__InterpreterSetValueWithAlloc(void *This, void *OutVal, void *OpaqueType) {
+  Value &V = *reinterpret_cast<Value *>(OutVal);
+  V = Value(This, OpaqueType, Value::K_PtrOrObj);
+  return V.getPtr();
+}
+
+// Pointers, lvalue struct that can take as a reference.
+void REPL_EXTERNAL_VISIBILITY __InterpreterSetValueNoAlloc(void *This,
+                                                           void *OutVal,
+                                                           void *OpaqueType,
+                                                           void *Val) {
+  Value &V = *reinterpret_cast<Value *>(OutVal);
+  V = Value(This, OpaqueType, Value::K_PtrOrObj);
+  V.setPtr(Val);
+}
+
+// All builtin types that are cheap to copy.
+#define X(type, name)                                                          \
+  void REPL_EXTERNAL_VISIBILITY __InterpreterSetValueNoAlloc(                  \
+      void *This, void *OutVal, void *OpaqueType, type Val) {                  \
+    Value &V = *reinterpret_cast<Value *>(OutVal);                             \
+    V = Value(This, OpaqueType, Value::K_##name);                              \
+    V.set##name(Val);                                                          \
+  }
+BUILTIN_TYPES
+#undef X
Index: clang/lib/Interpreter/IncrementalParser.h
===================================================================
--- clang/lib/Interpreter/IncrementalParser.h
+++ clang/lib/Interpreter/IncrementalParser.h
@@ -16,7 +16,7 @@
 #include "clang/Interpreter/PartialTranslationUnit.h"
 
 #include "clang/AST/GlobalDecl.h"
-
+#include "clang/Parse/Parser.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
@@ -32,7 +32,7 @@
 class CompilerInstance;
 class IncrementalAction;
 class Parser;
-
+class Interpreter;
 /// Provides support for incremental compilation. Keeps track of the state
 /// changes between the subsequent incremental input.
 ///
@@ -68,6 +68,8 @@
   /// \c TranslationUnitDecl and \c llvm::Module corresponding to the input.
   llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Input);
 
+  llvm::Expected<PartialTranslationUnit &> Parse(Parser::DeclGroupPtrTy D);
+
   /// Uses the CodeGenModule mangled name cache and avoids recomputing.
   ///\returns the mangled name of a \c GD.
   llvm::StringRef GetMangledName(GlobalDecl GD) const;
@@ -76,8 +78,11 @@
 
   std::list<PartialTranslationUnit> &getPTUs() { return PTUs; }
 
-private:
-  llvm::Expected<PartialTranslationUnit &> ParseOrWrapTopLevelDecl();
+  llvm::Expected<PartialTranslationUnit &>
+  ParseOrWrapTopLevelDecl(Parser::DeclGroupPtrTy SynthesizedDecl = nullptr);
+
+  bool isPrettyPrintMode() const { return P->isPrettyPrintMode(); }
+  void setPrettyPrintMode(bool Mode = true) { P->setPrettyPrintMode(Mode); }
 };
 } // end namespace clang
 
Index: clang/lib/Interpreter/IncrementalParser.cpp
===================================================================
--- clang/lib/Interpreter/IncrementalParser.cpp
+++ clang/lib/Interpreter/IncrementalParser.cpp
@@ -19,9 +19,9 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendAction.h"
 #include "clang/FrontendTool/Utils.h"
+#include "clang/Interpreter/Interpreter.h"
 #include "clang/Parse/Parser.h"
 #include "clang/Sema/Sema.h"
-
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/Error.h"
@@ -143,7 +143,8 @@
 }
 
 llvm::Expected<PartialTranslationUnit &>
-IncrementalParser::ParseOrWrapTopLevelDecl() {
+IncrementalParser::ParseOrWrapTopLevelDecl(
+    Parser::DeclGroupPtrTy SynthesizedDecl) {
   // Recover resources if we crash before exiting this method.
   Sema &S = CI->getSema();
   llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S);
@@ -169,14 +170,24 @@
     S.ActOnTranslationUnitScope(P->getCurScope());
   }
 
-  Parser::DeclGroupPtrTy ADecl;
-  Sema::ModuleImportState ImportState;
-  for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
-       AtEOF = P->ParseTopLevelDecl(ADecl, ImportState)) {
-    if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
-      return llvm::make_error<llvm::StringError>("Parsing failed. "
-                                                 "The consumer rejected a decl",
-                                                 std::error_code());
+  if (SynthesizedDecl) {
+    if (!Consumer->HandleTopLevelDecl(SynthesizedDecl.get())) {
+      return llvm::make_error<llvm::StringError>(
+          "Parsing failed. "
+          "The consumer rejected the synthesized decl",
+          std::error_code());
+    }
+  } else {
+    Parser::DeclGroupPtrTy ADecl;
+    Sema::ModuleImportState ImportState;
+    for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
+         AtEOF = P->ParseTopLevelDecl(ADecl, ImportState)) {
+      if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
+        return llvm::make_error<llvm::StringError>(
+            "Parsing failed. "
+            "The consumer rejected a decl",
+            std::error_code());
+    }
   }
 
   DiagnosticsEngine &Diags = getCI()->getDiagnostics();
@@ -278,6 +289,24 @@
   return PTU;
 }
 
+llvm::Expected<PartialTranslationUnit &>
+IncrementalParser::Parse(Parser::DeclGroupPtrTy D) {
+  llvm::Expected<PartialTranslationUnit &> PTUOrErr =
+      ParseOrWrapTopLevelDecl(D);
+  if (!PTUOrErr) {
+    return PTUOrErr.takeError();
+  }
+  if (CodeGenerator *CG = getCodeGen(Act.get())) {
+    std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
+    CG->StartModule("incr_module_" + std::to_string(PTUs.size()),
+                    M->getContext());
+
+    PTUOrErr.get().TheModule = std::move(M);
+  }
+
+  return PTUOrErr;
+}
+
 void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
   TranslationUnitDecl *MostRecentTU = PTU.TUPart;
   TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl();
Index: clang/lib/Interpreter/CMakeLists.txt
===================================================================
--- clang/lib/Interpreter/CMakeLists.txt
+++ clang/lib/Interpreter/CMakeLists.txt
@@ -12,6 +12,7 @@
   IncrementalExecutor.cpp
   IncrementalParser.cpp
   Interpreter.cpp
+  Value.cpp
 
   DEPENDS
   intrinsics_gen
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -439,6 +439,10 @@
   /// a statement expression and builds a suitable expression statement.
   StmtResult handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx);
 
+  /// A flag that indicate if we run into something that need to pretty print.
+  /// Note this should only be used in incremental C++ (clang-repl).
+  bool PrettyPrintMode = false;
+
 public:
   Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies);
   ~Parser() override;
@@ -459,6 +463,17 @@
     return Actions.getObjCDeclContext();
   }
 
+  bool isPrettyPrintMode() const {
+    assert(PP.isIncrementalProcessingEnabled() &&
+           "This should only be used in incremental C++");
+    return PrettyPrintMode;
+  }
+  void setPrettyPrintMode(bool Mode = true) {
+    assert(PP.isIncrementalProcessingEnabled() &&
+           "This should only be used in incremental C++");
+    PrettyPrintMode = Mode;
+  }
+
   // Type forwarding.  All of these are statically 'void*', but they may all be
   // different actual classes based on the actions in place.
   typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
@@ -1062,7 +1077,8 @@
   /// If the next token is not a semicolon, this emits the specified diagnostic,
   /// or, if there's just some closing-delimiter noise (e.g., ')' or ']') prior
   /// to the semicolon, consumes that extra token.
-  bool ExpectAndConsumeSemi(unsigned DiagID , StringRef TokenUsed = "");
+  bool ExpectAndConsumeSemi(unsigned DiagID, StringRef TokenUsed = "",
+                            bool IsTopExpr = false);
 
   /// The kind of extra semi diagnostic to emit.
   enum ExtraSemiKind {
Index: clang/include/clang/Interpreter/Value.h
===================================================================
--- /dev/null
+++ clang/include/clang/Interpreter/Value.h
@@ -0,0 +1,144 @@
+//===--- Interpreter.h - Incremental Compiation and Execution---*- 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 the class that used to represent a value in incremental
+// C++.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INTERPRETER_VALUE_H
+#define LLVM_CLANG_INTERPRETER_VALUE_H
+
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+
+namespace llvm {
+class raw_ostream;
+
+} // namespace llvm
+
+namespace clang {
+
+class ASTContext;
+class Interpreter;
+
+#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
+
+class Interpreter;
+class QualType;
+
+#define BUILTIN_TYPES                                                          \
+  X(bool, Bool)                                                                \
+  X(char, Char)                                                                \
+  X(signed char, SChar)                                                        \
+  X(unsigned char, UChar)                                                      \
+  X(short, Short)                                                              \
+  X(unsigned short, UShort)                                                    \
+  X(int, Int)                                                                  \
+  X(unsigned int, UInt)                                                        \
+  X(long, Long)                                                                \
+  X(unsigned long, ULong)                                                      \
+  X(long long, LongLong)                                                       \
+  X(unsigned long long, ULongLong)                                             \
+  X(float, Float)                                                              \
+  X(double, Double)
+
+class REPL_EXTERNAL_VISIBILITY Value {
+  union Storage {
+#define X(type, name) type m_##name;
+    BUILTIN_TYPES
+#undef X
+    void *m_Ptr;
+  };
+
+public:
+  enum Kind {
+#define X(type, name) K_##name,
+    BUILTIN_TYPES
+#undef X
+
+        K_Void,
+    K_PtrOrObj,
+    K_Unspecified
+  };
+
+  Value() = default;
+  Value(void /*Interpreter*/ *In, void /*QualType*/ *Ty, Kind K);
+  Value(const Value &RHS);
+  Value(Value &&RHS) noexcept;
+  Value &operator=(const Value &RHS);
+  Value &operator=(Value &&RHS) noexcept;
+  ~Value();
+
+  void print(llvm::raw_ostream &Out) const;
+  void dump() const;
+
+  ASTContext &getASTContext();
+  QualType getType() const;
+  Interpreter &getInterpreter();
+
+  bool isValid() const { return ValueKind != K_Unspecified; }
+  bool isVoid() const { return ValueKind == K_Void; }
+  Kind getKind() const { return ValueKind; }
+  void setKind(Kind K) { ValueKind = K; }
+  void setOpaqueType(void *Ty) { OpaqueType = Ty; }
+
+  void setPtr(void *Ptr) { Data.m_Ptr = Ptr; }
+
+  void *getPtr() const {
+    assert(ValueKind == K_PtrOrObj);
+    return Data.m_Ptr;
+  }
+
+#define X(type, name)                                                          \
+  void set##name(type Val) {                                                   \
+    Data.m_##name = Val;                                                       \
+    ValueKind = K_##name;                                                      \
+  }                                                                            \
+  type get##name() const {                                                     \
+    assert(ValueKind == K_##name);                                             \
+    return Data.m_##name;                                                      \
+  }
+  BUILTIN_TYPES
+#undef X
+
+  template <typename T> T getAs();
+
+// Allows us to have overloads for each builtin type, plus one that goes via
+// void*
+#define X(type, name)                                                          \
+  template <> type getAs() {                                                   \
+    assert(ValueKind == K_##name);                                             \
+    return (type)Data.m_##name;                                                \
+  }
+  BUILTIN_TYPES
+#undef X
+
+private:
+  // Interpreter, QualType are stored as void* to reduce dependencies.
+  void *Interp = nullptr;
+  void *OpaqueType = nullptr;
+  Storage Data;
+  Kind ValueKind = K_Unspecified;
+  bool IsManuallyAlloc = false;
+};
+
+} // namespace clang
+#endif
Index: clang/include/clang/Interpreter/Interpreter.h
===================================================================
--- clang/include/clang/Interpreter/Interpreter.h
+++ clang/include/clang/Interpreter/Interpreter.h
@@ -14,10 +14,12 @@
 #ifndef LLVM_CLANG_INTERPRETER_INTERPRETER_H
 #define LLVM_CLANG_INTERPRETER_INTERPRETER_H
 
-#include "clang/Interpreter/PartialTranslationUnit.h"
-
+#include "clang/AST/Decl.h"
 #include "clang/AST/GlobalDecl.h"
+#include "clang/Interpreter/PartialTranslationUnit.h"
+#include "clang/Interpreter/Value.h"
 
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/Support/Error.h"
 
@@ -28,7 +30,7 @@
 namespace orc {
 class LLJIT;
 class ThreadSafeContext;
-}
+} // namespace orc
 } // namespace llvm
 
 namespace clang {
@@ -56,18 +58,13 @@
   ~Interpreter();
   static llvm::Expected<std::unique_ptr<Interpreter>>
   create(std::unique_ptr<CompilerInstance> CI);
+  ASTContext &getASTContext() const;
   const CompilerInstance *getCompilerInstance() const;
   const llvm::orc::LLJIT *getExecutionEngine() const;
   llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);
   llvm::Error Execute(PartialTranslationUnit &T);
-  llvm::Error ParseAndExecute(llvm::StringRef Code) {
-    auto PTU = Parse(Code);
-    if (!PTU)
-      return PTU.takeError();
-    if (PTU->TheModule)
-      return Execute(*PTU);
-    return llvm::Error::success();
-  }
+  llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr);
+  llvm::Expected<void *> CompileDtorCall(const RecordDecl *RD);
 
   /// Undo N previous incremental inputs.
   llvm::Error Undo(unsigned N = 1);
@@ -85,6 +82,22 @@
   /// file.
   llvm::Expected<llvm::JITTargetAddress>
   getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
+
+  // FIXME: Make it private.
+  Expr *RuntimeNoAllocInterface = nullptr;
+  Expr *RuntimeAllocInterface = nullptr;
+
+private:
+  llvm::Expected<Expr *> CaptureExpr(TranslationUnitDecl &TU);
+
+  bool FindRuntimeInterface();
+
+  std::pair<llvm::Expected<PartialTranslationUnit &>, FunctionDecl *>
+  SynthesizePTU(clang::Expr *E);
+
+  llvm::Error GenerateValue(TranslationUnitDecl &TU, Value *V);
+
+  llvm::DenseMap<const RecordDecl *, void *> Dtors;
 };
 } // namespace clang
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to