[PATCH] D156858: Add Documentation for Execution Results Handling in Clang-REPL

2023-08-05 Thread Jun Zhang via Phabricator via cfe-commits
junaire added a comment.

I want to clarify: We offer two features: 1. capture the execution results and 
bring it back to the compiled program. 2. dump the captured value (value 
printing/automatic printf) and all the parsing, ast transform and balabala, 
these are all implementation details. The doc looks fine but may need a bit of 
restructuring. I'd suggest you split them into:

1. what do we offer? what are the new features? why are they important? The two 
I mentioned above
2. how these are implemented? what does the underhood look like? annotation 
token, code synthesis, etc...
3. further information, RFC and etc...


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156858

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/lib/Interpreter/ValuePrinter.cpp:262
+
+static llvm::Expected CompileDecl(Interpreter ,
+   Decl *D) {

v.g.vassilev wrote:
> Let's add a FIXME here. The problem `CompileDecl` and `GenModule` intends to 
> solve is that when we synthesize AST we need to inform the rest of the Clang 
> infrastructure about it and attach the produced `llvm::Module` to the JIT so 
> that it can resolve symbols from it.
> 
> In cling that is solved with a RAII object which marks a scope where the 
> synthesis happens and takes care to inform the rest of the infrastructure. We 
> need something similar and a little more robust maybe. Something like 
> `ASTSynthesisRAII` which ultimately hides this machinery especially from the 
> public API.
I can't really get the point. I agree we shouldn't expose 
`Interpreter::GenModule` as a public interface but I don't understand the 
solution.



Comment at: clang/lib/Interpreter/ValuePrinter.cpp:442
+
+REPL_EXTERNAL_VISIBILITY std::string PrintValueRuntime(const char *const *Val) 
{
+  return PrintString(Val);

v.g.vassilev wrote:
> All of the `PrintValueRuntime` seem to be duplicating code. We could use the 
> preprocessor to expand these to but it would require some changes which I 
> believe could be done as a separate patch:
> 
> * Perhaps we should be compatible with cling here in terms of naming as 
> that's a public API - there I believe we use `printValue`.
> * We should try to leverage `TemplateBase.cpp::printIntegral` for integral 
> types.
> * We should not return `std::string` here but a `const char*` and we should 
> provide somewhere storage for them. That would probably make porting to 
> embedded systems easier since on many the  header is hard to support. 
> 
> I believe it would be enough to have a fixme for now.
* I'd propose using `PrintValueRuntime` here. This is because we have used it 
across RFC and other documentation so I don't want to change it :(

> We should not return std::string here but a const char* and we should provide 
> somewhere storage for them. That would probably make porting to embedded 
> systems easier since on many the  header is hard to support.

* That really touches the dark corner of our design. On the one hand, we try to 
keep `Value` itself as lightweight as possible, on the other hand, we use heavy 
headers like `` and `` in value pretty printing. While 
this is awkward, we can hardly avoid it because the implementation needs to see 
the definition of these types to know how to print it. So how can we do this on 
resources limited systems? My point is that perhaps we can keep it as is, 
because it's very hard to measure how expensive the feature is on the targeting 
platform. If the system can afford this, then we don't need to worry about 
anything, but if the system can't even use STL itself, presumably it shouldn't 
use value printing at all! Note that this doesn't conflicts with the lightness 
of the value runtime as it SHOULD add as little overhead as possible no matter 
whether the host can afford it or not.



Comment at: clang/lib/Interpreter/ValuePrinter.cpp:473
+  else if (auto *BT = DesugaredTy.getCanonicalType()->getAs()) {
+switch (BT->getKind()) {
+case BuiltinType::Bool: {

v.g.vassilev wrote:
> We could use the preprocessor the way we do in `Value.cpp` to expand this 
> dispatcher.
We actually can't because it doesn't strictly match everything. For example 
`Char_S` and `SChar` both map to `V.getSChar()` IIUC?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 526566.
junaire marked 2 inline comments as done.
junaire added a comment.

Add LLVM preamble


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/PartialTranslationUnit.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/DeviceOffload.cpp
  clang/lib/Interpreter/DeviceOffload.h
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/tools/clang-repl/ClangRepl.cpp
  clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
  clang/unittests/Interpreter/IncrementalProcessingTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ 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 @@
   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) {
Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp
===
--- clang/unittests/Interpreter/IncrementalProcessingTest.cpp
+++ clang/unittests/Interpreter/IncrementalProcessingTest.cpp
@@ -27,6 +27,7 @@
 
 using namespace llvm;
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 
@@ -52,12 +53,12 @@
 
 TEST(IncrementalProcessing, EmitCXXGlobalInitFunc) {
   std::vector 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 PTUs;
+  std::array PTUs;
 
   PTUs[0] = ::cantFail(Interp->Parse(TestProgram1));
   ASSERT_TRUE(PTUs[0]->TheModule);
Index: clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
===
--- clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -30,6 +30,7 @@
 #include "gtest/gtest.h"
 
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 using Args = std::vector;
@@ -38,12 +39,12 @@
   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) {
Index: clang/tools/clang-repl/ClangRepl.cpp
===
--- clang/tools/clang-repl/ClangRepl.cpp
+++ clang/tools/clang-repl/ClangRepl.cpp
@@ -97,7 +97,7 @@
 return 0;
   }
 
-  clang::IncrementalCompilerBuilder CB;
+  clang::caas::IncrementalCompilerBuilder CB;
   CB.SetCompilerArgs(ClangArgv);
 
   std::unique_ptr DeviceCI;
@@ -132,10 +132,10 @@
   if (CudaEnabled)
 DeviceCI->LoadRequestedPlugins();
 
-  std::unique_ptr Interp;
+  std::unique_ptr Interp;
   if (CudaEnabled) {
-Interp = ExitOnErr(
-clang::Interpreter::createWithCUDA(std::move(CI), 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-29 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/tools/clang-repl/CMakeLists.txt:40
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@PEBX@Z
+  
??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@P6AAEAV01@AEAV01@@Z@Z
+  
??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@D@Z

v.g.vassilev wrote:
> v.g.vassilev wrote:
> > We should check if there is a better way to export a subset of symbols 
> > through the llvm build system. Maybe @lhames, @sunho or @sgraenitz know how.
> I wonder if that's related to https://reviews.llvm.org/D151620 in some way? 
> That is, does D151620 fix our exports and this section becomes redundant?
I haven't tested that but I don't think so. The patch you posted is about 
fixing issues on particular platforms like MinGW.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-29 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 526383.
junaire added a comment.

Make CreateUniqName a static helper


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/PartialTranslationUnit.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/DeviceOffload.cpp
  clang/lib/Interpreter/DeviceOffload.h
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/tools/clang-repl/ClangRepl.cpp
  clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
  clang/unittests/Interpreter/IncrementalProcessingTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ 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 @@
   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) {
Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp
===
--- clang/unittests/Interpreter/IncrementalProcessingTest.cpp
+++ clang/unittests/Interpreter/IncrementalProcessingTest.cpp
@@ -27,6 +27,7 @@
 
 using namespace llvm;
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 
@@ -52,12 +53,12 @@
 
 TEST(IncrementalProcessing, EmitCXXGlobalInitFunc) {
   std::vector 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 PTUs;
+  std::array PTUs;
 
   PTUs[0] = ::cantFail(Interp->Parse(TestProgram1));
   ASSERT_TRUE(PTUs[0]->TheModule);
Index: clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
===
--- clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -30,6 +30,7 @@
 #include "gtest/gtest.h"
 
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 using Args = std::vector;
@@ -38,12 +39,12 @@
   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) {
Index: clang/tools/clang-repl/ClangRepl.cpp
===
--- clang/tools/clang-repl/ClangRepl.cpp
+++ clang/tools/clang-repl/ClangRepl.cpp
@@ -97,7 +97,7 @@
 return 0;
   }
 
-  clang::IncrementalCompilerBuilder CB;
+  clang::caas::IncrementalCompilerBuilder CB;
   CB.SetCompilerArgs(ClangArgv);
 
   std::unique_ptr DeviceCI;
@@ -132,10 +132,10 @@
   if (CudaEnabled)
 DeviceCI->LoadRequestedPlugins();
 
-  std::unique_ptr Interp;
+  std::unique_ptr Interp;
   if (CudaEnabled) {
-Interp = ExitOnErr(
-clang::Interpreter::createWithCUDA(std::move(CI), std::move(DeviceCI)));
+  

[PATCH] D151620: [clang-repl] Fix REPL_EXTERNAL_VISIBILITY and building libclang-cpp.dll for MinGW configurations

2023-05-28 Thread Jun Zhang via Phabricator via cfe-commits
junaire accepted this revision.
junaire added a comment.
This revision is now accepted and ready to land.

Thanks.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D151620

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-27 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 526256.
junaire added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/PartialTranslationUnit.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/DeviceOffload.cpp
  clang/lib/Interpreter/DeviceOffload.h
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/tools/clang-repl/ClangRepl.cpp
  clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
  clang/unittests/Interpreter/IncrementalProcessingTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ 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 @@
   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) {
Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp
===
--- clang/unittests/Interpreter/IncrementalProcessingTest.cpp
+++ clang/unittests/Interpreter/IncrementalProcessingTest.cpp
@@ -27,6 +27,7 @@
 
 using namespace llvm;
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 
@@ -52,12 +53,12 @@
 
 TEST(IncrementalProcessing, EmitCXXGlobalInitFunc) {
   std::vector 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 PTUs;
+  std::array PTUs;
 
   PTUs[0] = ::cantFail(Interp->Parse(TestProgram1));
   ASSERT_TRUE(PTUs[0]->TheModule);
Index: clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
===
--- clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -30,6 +30,7 @@
 #include "gtest/gtest.h"
 
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 using Args = std::vector;
@@ -38,12 +39,12 @@
   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) {
Index: clang/tools/clang-repl/ClangRepl.cpp
===
--- clang/tools/clang-repl/ClangRepl.cpp
+++ clang/tools/clang-repl/ClangRepl.cpp
@@ -97,7 +97,7 @@
 return 0;
   }
 
-  clang::IncrementalCompilerBuilder CB;
+  clang::caas::IncrementalCompilerBuilder CB;
   CB.SetCompilerArgs(ClangArgv);
 
   std::unique_ptr DeviceCI;
@@ -132,10 +132,10 @@
   if (CudaEnabled)
 DeviceCI->LoadRequestedPlugins();
 
-  std::unique_ptr Interp;
+  std::unique_ptr Interp;
   if (CudaEnabled) {
-Interp = ExitOnErr(
-clang::Interpreter::createWithCUDA(std::move(CI), std::move(DeviceCI)));
+Interp = 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-24 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 525425.
junaire added a comment.

Remove `Interpereter::getParser` + More clean up


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/PartialTranslationUnit.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/tools/clang-repl/ClangRepl.cpp
  clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
  clang/unittests/Interpreter/IncrementalProcessingTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ 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,10 +47,11 @@
   DiagnosticConsumer *Client = nullptr) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
-  auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs));
+  auto CI =
+  cantFail(clang::caas::IncrementalCompilerBuilder::create(ClangArgs));
   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) {
Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp
===
--- clang/unittests/Interpreter/IncrementalProcessingTest.cpp
+++ clang/unittests/Interpreter/IncrementalProcessingTest.cpp
@@ -27,6 +27,7 @@
 
 using namespace llvm;
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 
@@ -55,7 +56,7 @@
   auto CI = llvm::cantFail(IncrementalCompilerBuilder::create(ClangArgv));
   auto Interp = llvm::cantFail(Interpreter::create(std::move(CI)));
 
-  std::array PTUs;
+  std::array PTUs;
 
   PTUs[0] = ::cantFail(Interp->Parse(TestProgram1));
   ASSERT_TRUE(PTUs[0]->TheModule);
Index: clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
===
--- clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -30,6 +30,7 @@
 #include "gtest/gtest.h"
 
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 using Args = std::vector;
@@ -38,10 +39,11 @@
   DiagnosticConsumer *Client = nullptr) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
-  auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs));
+  auto CI =
+  cantFail(clang::caas::IncrementalCompilerBuilder::create(ClangArgs));
   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) {
Index: clang/tools/clang-repl/ClangRepl.cpp
===
--- clang/tools/clang-repl/ClangRepl.cpp
+++ clang/tools/clang-repl/ClangRepl.cpp
@@ -92,7 +92,8 @@
 
   // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
   // can replace the boilerplate code for creation of the compiler instance.
-  auto CI = ExitOnErr(clang::IncrementalCompilerBuilder::create(ClangArgv));
+  auto CI =
+  ExitOnErr(clang::caas::IncrementalCompilerBuilder::create(ClangArgv));
 
   // Set an error handler, so that any LLVM backend diagnostics go through our
   // error handler.
@@ -102,7 +103,7 @@
   // Load any requested plugins.
   CI->LoadRequestedPlugins();
 
-  auto Interp = ExitOnErr(clang::Interpreter::create(std::move(CI)));
+  auto Interp = ExitOnErr(clang::caas::Interpreter::create(std::move(CI)));
   for (const std::string  : OptInputs) {
 if (auto Err = 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-24 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/lib/Interpreter/Interpreter.cpp:434
+
+llvm::Expected Interpreter::CompileDecl(Decl *D) {
+  assert(D && "The Decl being compiled can't be null");

aaron.ballman wrote:
> Any way to make this take a `const Decl *` instead?
`DeclGroupRef` in line 439 asks a non-const Decl*, should we use `const Decl*` 
and const cast it?



Comment at: clang/lib/Interpreter/Value.cpp:272
+
 void Value::print(llvm::raw_ostream ) const {
   assert(OpaqueType != nullptr && "Can't print default Value");

v.g.vassilev wrote:
> We should add some documentation for users how to write a pretty-printer for 
> a custom class.
> 
> We do not seem to support the multiple inheritance case where one of the base 
> classes has a pretty-printer and the other does not. See the explanation in 
> Cling. It is okay to not have it at the moment but we should include a FIXME 
> here saying that we do not yet support it.
Where should I put the doc? Value.cpp is the implementation and it's unlikely 
for regular users to read it.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-24 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 525420.
junaire marked 15 inline comments as done.
junaire added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/PartialTranslationUnit.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/tools/clang-repl/ClangRepl.cpp
  clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
  clang/unittests/Interpreter/IncrementalProcessingTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ 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,10 +47,11 @@
   DiagnosticConsumer *Client = nullptr) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
-  auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs));
+  auto CI =
+  cantFail(clang::caas::IncrementalCompilerBuilder::create(ClangArgs));
   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) {
Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp
===
--- clang/unittests/Interpreter/IncrementalProcessingTest.cpp
+++ clang/unittests/Interpreter/IncrementalProcessingTest.cpp
@@ -27,6 +27,7 @@
 
 using namespace llvm;
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 
@@ -55,7 +56,7 @@
   auto CI = llvm::cantFail(IncrementalCompilerBuilder::create(ClangArgv));
   auto Interp = llvm::cantFail(Interpreter::create(std::move(CI)));
 
-  std::array PTUs;
+  std::array PTUs;
 
   PTUs[0] = ::cantFail(Interp->Parse(TestProgram1));
   ASSERT_TRUE(PTUs[0]->TheModule);
Index: clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
===
--- clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -30,6 +30,7 @@
 #include "gtest/gtest.h"
 
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 using Args = std::vector;
@@ -38,10 +39,11 @@
   DiagnosticConsumer *Client = nullptr) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
-  auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs));
+  auto CI =
+  cantFail(clang::caas::IncrementalCompilerBuilder::create(ClangArgs));
   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) {
Index: clang/tools/clang-repl/ClangRepl.cpp
===
--- clang/tools/clang-repl/ClangRepl.cpp
+++ clang/tools/clang-repl/ClangRepl.cpp
@@ -92,7 +92,8 @@
 
   // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
   // can replace the boilerplate code for creation of the compiler instance.
-  auto CI = ExitOnErr(clang::IncrementalCompilerBuilder::create(ClangArgv));
+  auto CI =
+  ExitOnErr(clang::caas::IncrementalCompilerBuilder::create(ClangArgv));
 
   // Set an error handler, so that any LLVM backend diagnostics go through our
   // error handler.
@@ -102,7 +103,7 @@
   // Load any requested plugins.
   CI->LoadRequestedPlugins();
 
-  auto Interp = ExitOnErr(clang::Interpreter::create(std::move(CI)));
+  auto Interp = ExitOnErr(clang::caas::Interpreter::create(std::move(CI)));
   for (const std::string  : OptInputs) {
 if (auto Err = 

[PATCH] D150937: [clang-repl] Disable all tests on unsupported platforms

2023-05-23 Thread Jun Zhang via Phabricator via cfe-commits
junaire abandoned this revision.
junaire added a comment.

This isn't an ideal solution after an off-list discussion.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D150937

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-21 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 524096.
junaire added a comment.

.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/PartialTranslationUnit.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/tools/clang-repl/ClangRepl.cpp
  clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
  clang/unittests/Interpreter/IncrementalProcessingTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ 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,10 +47,11 @@
   DiagnosticConsumer *Client = nullptr) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
-  auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs));
+  auto CI =
+  cantFail(clang::caas::IncrementalCompilerBuilder::create(ClangArgs));
   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) {
Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp
===
--- clang/unittests/Interpreter/IncrementalProcessingTest.cpp
+++ clang/unittests/Interpreter/IncrementalProcessingTest.cpp
@@ -27,6 +27,7 @@
 
 using namespace llvm;
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 
@@ -55,7 +56,7 @@
   auto CI = llvm::cantFail(IncrementalCompilerBuilder::create(ClangArgv));
   auto Interp = llvm::cantFail(Interpreter::create(std::move(CI)));
 
-  std::array PTUs;
+  std::array PTUs;
 
   PTUs[0] = ::cantFail(Interp->Parse(TestProgram1));
   ASSERT_TRUE(PTUs[0]->TheModule);
Index: clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
===
--- clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -30,6 +30,7 @@
 #include "gtest/gtest.h"
 
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 using Args = std::vector;
@@ -38,10 +39,11 @@
   DiagnosticConsumer *Client = nullptr) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
-  auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs));
+  auto CI =
+  cantFail(clang::caas::IncrementalCompilerBuilder::create(ClangArgs));
   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) {
Index: clang/tools/clang-repl/ClangRepl.cpp
===
--- clang/tools/clang-repl/ClangRepl.cpp
+++ clang/tools/clang-repl/ClangRepl.cpp
@@ -92,7 +92,8 @@
 
   // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
   // can replace the boilerplate code for creation of the compiler instance.
-  auto CI = ExitOnErr(clang::IncrementalCompilerBuilder::create(ClangArgv));
+  auto CI =
+  ExitOnErr(clang::caas::IncrementalCompilerBuilder::create(ClangArgv));
 
   // Set an error handler, so that any LLVM backend diagnostics go through our
   // error handler.
@@ -102,7 +103,7 @@
   // Load any requested plugins.
   CI->LoadRequestedPlugins();
 
-  auto Interp = ExitOnErr(clang::Interpreter::create(std::move(CI)));
+  auto Interp = ExitOnErr(clang::caas::Interpreter::create(std::move(CI)));
   for (const std::string  : OptInputs) {
 if (auto Err = Interp->ParseAndExecute(input))
   

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-21 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 524093.
junaire added a comment.

add `caas` namespace


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/PartialTranslationUnit.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/tools/clang-repl/ClangRepl.cpp
  clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
  clang/unittests/Interpreter/IncrementalProcessingTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ 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,10 +47,11 @@
   DiagnosticConsumer *Client = nullptr) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
-  auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs));
+  auto CI =
+  cantFail(clang::caas::IncrementalCompilerBuilder::create(ClangArgs));
   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) {
Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp
===
--- clang/unittests/Interpreter/IncrementalProcessingTest.cpp
+++ clang/unittests/Interpreter/IncrementalProcessingTest.cpp
@@ -27,6 +27,7 @@
 
 using namespace llvm;
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 
@@ -55,7 +56,7 @@
   auto CI = llvm::cantFail(IncrementalCompilerBuilder::create(ClangArgv));
   auto Interp = llvm::cantFail(Interpreter::create(std::move(CI)));
 
-  std::array PTUs;
+  std::array PTUs;
 
   PTUs[0] = ::cantFail(Interp->Parse(TestProgram1));
   ASSERT_TRUE(PTUs[0]->TheModule);
Index: clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
===
--- clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -30,6 +30,7 @@
 #include "gtest/gtest.h"
 
 using namespace clang;
+using namespace clang::caas;
 
 namespace {
 using Args = std::vector;
@@ -38,10 +39,11 @@
   DiagnosticConsumer *Client = nullptr) {
   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
-  auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs));
+  auto CI =
+  cantFail(clang::caas::IncrementalCompilerBuilder::create(ClangArgs));
   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) {
Index: clang/tools/clang-repl/ClangRepl.cpp
===
--- clang/tools/clang-repl/ClangRepl.cpp
+++ clang/tools/clang-repl/ClangRepl.cpp
@@ -92,7 +92,8 @@
 
   // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It
   // can replace the boilerplate code for creation of the compiler instance.
-  auto CI = ExitOnErr(clang::IncrementalCompilerBuilder::create(ClangArgv));
+  auto CI =
+  ExitOnErr(clang::caas::IncrementalCompilerBuilder::create(ClangArgv));
 
   // Set an error handler, so that any LLVM backend diagnostics go through our
   // error handler.
@@ -102,7 +103,7 @@
   // Load any requested plugins.
   CI->LoadRequestedPlugins();
 
-  auto Interp = ExitOnErr(clang::Interpreter::create(std::move(CI)));
+  auto Interp = ExitOnErr(clang::caas::Interpreter::create(std::move(CI)));
   for (const std::string  : OptInputs) {
 if (auto Err = Interp->ParseAndExecute(input))
   

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-21 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 524091.
junaire added a comment.

.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt

Index: clang/tools/clang-repl/CMakeLists.txt
===
--- clang/tools/clang-repl/CMakeLists.txt
+++ clang/tools/clang-repl/CMakeLists.txt
@@ -11,6 +11,65 @@
   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@std@@3Unothrow_t@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@YAPEAX_K@Z
+  ??3@YAXPEAX@Z
+  ??_U@YAPEAX_K@Z
+  ??_V@YAXPEAX@Z
+  ??3@YAXPEAX_K@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@PEBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@P6AAEAV01@AEAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z
+  ?_Facet_Register@std@@YAXPEAV_Facet_base@1@@Z
+)
+  else()
+set(clang_repl_exports ${clang_repl_exports}
+  ??2@YAPAXI@Z
+  ??3@YAXPAX@Z
+  ??3@YAXPAXI@Z
+  ??_U@YAPAXI@Z
+  ??_V@YAXPAX@Z
+  ??_V@YAXPAXI@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@PBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z
+  ?_Facet_Register@std@@YAXPAV_Facet_base@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
Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,180 @@
+// 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 -fno-delayed-template-parsing | FileCheck %s
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-21 Thread Jun Zhang via Phabricator via cfe-commits
junaire added a comment.

Invite more people to the party :)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-21 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 524088.
junaire added a comment.

.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt

Index: clang/tools/clang-repl/CMakeLists.txt
===
--- clang/tools/clang-repl/CMakeLists.txt
+++ clang/tools/clang-repl/CMakeLists.txt
@@ -11,6 +11,65 @@
   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@std@@3Unothrow_t@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@YAPEAX_K@Z
+  ??3@YAXPEAX@Z
+  ??_U@YAPEAX_K@Z
+  ??_V@YAXPEAX@Z
+  ??3@YAXPEAX_K@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@PEBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@P6AAEAV01@AEAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z
+  ?_Facet_Register@std@@YAXPEAV_Facet_base@1@@Z
+)
+  else()
+set(clang_repl_exports ${clang_repl_exports}
+  ??2@YAPAXI@Z
+  ??3@YAXPAX@Z
+  ??3@YAXPAXI@Z
+  ??_U@YAPAXI@Z
+  ??_V@YAXPAX@Z
+  ??_V@YAXPAXI@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@PBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z
+  ?_Facet_Register@std@@YAXPAV_Facet_base@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
Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,180 @@
+// 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 -fno-delayed-template-parsing | FileCheck %s
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: 

[PATCH] D150937: [clang-repl] Disable all tests on unsupported platforms

2023-05-19 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 523697.
junaire added a comment.

.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D150937

Files:
  clang/test/Interpreter/incremental-mode.cpp
  clang/unittests/Interpreter/IncrementalProcessingTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -40,6 +40,15 @@
 REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
 
 namespace {
+
+bool HostSupportsJit() {
+  auto J = llvm::orc::LLJITBuilder().create();
+  if (J)
+return true;
+  LLVMConsumeError(llvm::wrap(J.takeError()));
+  return false;
+}
+
 using Args = std::vector;
 static std::unique_ptr
 createInterpreter(const Args  = {},
@@ -56,7 +65,14 @@
   return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
 }
 
+#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
+TEST(InterpreterTest, DISABLED_Sanity) {
+#else
 TEST(InterpreterTest, Sanity) {
+#endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
   std::unique_ptr Interp = createInterpreter();
 
   using PTU = PartialTranslationUnit;
@@ -72,7 +88,14 @@
   return llvm::cast(D)->getQualifiedNameAsString();
 }
 
+#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
+TEST(InterpreterTest, DISABLED_IncrementalInputTopLevelDecls) {
+#else
 TEST(InterpreterTest, IncrementalInputTopLevelDecls) {
+#endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
   std::unique_ptr Interp = createInterpreter();
   auto R1 = Interp->Parse("int var1 = 42; int f() { return var1; }");
   // gtest doesn't expand into explicit bool conversions.
@@ -89,7 +112,14 @@
   EXPECT_EQ("var2", DeclToString(*R2DeclRange.begin()));
 }
 
+#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
+TEST(InterpreterTest, DISABLED_Errors) {
+#else
 TEST(InterpreterTest, Errors) {
+#endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
   Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
 
   // Create the diagnostic engine with unowned consumer.
@@ -112,7 +142,14 @@
 // Here we test whether the user can mix declarations and statements. The
 // interpreter should be smart enough to recognize the declarations from the
 // statements and wrap the latter into a declaration, producing valid code.
+#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
+TEST(InterpreterTest, DISABLED_DeclsAndStatements) {
+#else
 TEST(InterpreterTest, DeclsAndStatements) {
+#endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
   Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
 
   // Create the diagnostic engine with unowned consumer.
@@ -134,7 +171,14 @@
   EXPECT_TRUE(!!R2);
 }
 
+#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
+TEST(InterpreterTest, DISABLED_UndoCommand) {
+#else
 TEST(InterpreterTest, UndoCommand) {
+#endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
   Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
 
   // Create the diagnostic engine with unowned consumer.
@@ -188,14 +232,6 @@
   return RawStr.str();
 }
 
-static bool HostSupportsJit() {
-  auto J = llvm::orc::LLJITBuilder().create();
-  if (J)
-return true;
-  LLVMConsumeError(llvm::wrap(J.takeError()));
-  return false;
-}
-
 struct LLVMInitRAII {
   LLVMInitRAII() {
 llvm::InitializeNativeTarget();
@@ -209,6 +245,9 @@
 #else
 TEST(IncrementalProcessing, FindMangledNameSymbol) {
 #endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
 
   std::unique_ptr Interp = createInterpreter();
 
@@ -216,11 +255,6 @@
   EXPECT_EQ(1U, DeclsSize(PTU.TUPart));
   auto R1DeclRange = PTU.TUPart->decls();
 
-  // We cannot execute on the platform.
-  if (!HostSupportsJit()) {
-return;
-  }
-
   NamedDecl *FD = cast(*R1DeclRange.begin());
   // Lower the PTU
   if (llvm::Error Err = Interp->Execute(PTU)) {
@@ -276,6 +310,10 @@
 #else
 TEST(IncrementalProcessing, InstantiateTemplate) {
 #endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
+
   // FIXME: We cannot yet handle delayed template parsing. If we run with
   // -fdelayed-template-parsing we try adding the newly created decl to the
   // active PTU which causes an assert.
@@ -292,11 +330,6 @@
   auto PTUDeclRange = PTU.TUPart->decls();
   EXPECT_EQ(1, std::distance(PTUDeclRange.begin(), PTUDeclRange.end()));
 
-  // We cannot execute on the platform.
-  if (!HostSupportsJit()) {
-return;
-  }
-
   // Lower the PTU
   if (llvm::Error Err = Interp->Execute(PTU)) {
 // We cannot execute on the platform.
Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp

[PATCH] D150937: [clang-repl] Disable all tests on unsupported platforms

2023-05-19 Thread Jun Zhang via Phabricator via cfe-commits
junaire created this revision.
Herald added a project: All.
junaire requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Signed-off-by: Jun Zhang 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D150937

Files:
  clang/unittests/Interpreter/IncrementalProcessingTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -40,6 +40,15 @@
 REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
 
 namespace {
+
+bool HostSupportsJit() {
+  auto J = llvm::orc::LLJITBuilder().create();
+  if (J)
+return true;
+  LLVMConsumeError(llvm::wrap(J.takeError()));
+  return false;
+}
+
 using Args = std::vector;
 static std::unique_ptr
 createInterpreter(const Args  = {},
@@ -56,7 +65,14 @@
   return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
 }
 
+#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
+TEST(InterpreterTest, DISABLED_Sanity) {
+#else
 TEST(InterpreterTest, Sanity) {
+#endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
   std::unique_ptr Interp = createInterpreter();
 
   using PTU = PartialTranslationUnit;
@@ -72,7 +88,14 @@
   return llvm::cast(D)->getQualifiedNameAsString();
 }
 
+#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
+TEST(InterpreterTest, DISABLED_IncrementalInputTopLevelDecls) {
+#else
 TEST(InterpreterTest, IncrementalInputTopLevelDecls) {
+#endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
   std::unique_ptr Interp = createInterpreter();
   auto R1 = Interp->Parse("int var1 = 42; int f() { return var1; }");
   // gtest doesn't expand into explicit bool conversions.
@@ -89,7 +112,14 @@
   EXPECT_EQ("var2", DeclToString(*R2DeclRange.begin()));
 }
 
+#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
+TEST(InterpreterTest, DISABLED_Errors) {
+#else
 TEST(InterpreterTest, Errors) {
+#endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
   Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
 
   // Create the diagnostic engine with unowned consumer.
@@ -112,7 +142,14 @@
 // Here we test whether the user can mix declarations and statements. The
 // interpreter should be smart enough to recognize the declarations from the
 // statements and wrap the latter into a declaration, producing valid code.
+#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
+TEST(InterpreterTest, DISABLED_DeclsAndStatements) {
+#else
 TEST(InterpreterTest, DeclsAndStatements) {
+#endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
   Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
 
   // Create the diagnostic engine with unowned consumer.
@@ -134,7 +171,14 @@
   EXPECT_TRUE(!!R2);
 }
 
+#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
+TEST(InterpreterTest, DISABLED_UndoCommand) {
+#else
 TEST(InterpreterTest, UndoCommand) {
+#endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
   Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
 
   // Create the diagnostic engine with unowned consumer.
@@ -188,14 +232,6 @@
   return RawStr.str();
 }
 
-static bool HostSupportsJit() {
-  auto J = llvm::orc::LLJITBuilder().create();
-  if (J)
-return true;
-  LLVMConsumeError(llvm::wrap(J.takeError()));
-  return false;
-}
-
 struct LLVMInitRAII {
   LLVMInitRAII() {
 llvm::InitializeNativeTarget();
@@ -209,6 +245,9 @@
 #else
 TEST(IncrementalProcessing, FindMangledNameSymbol) {
 #endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
 
   std::unique_ptr Interp = createInterpreter();
 
@@ -216,11 +255,6 @@
   EXPECT_EQ(1U, DeclsSize(PTU.TUPart));
   auto R1DeclRange = PTU.TUPart->decls();
 
-  // We cannot execute on the platform.
-  if (!HostSupportsJit()) {
-return;
-  }
-
   NamedDecl *FD = cast(*R1DeclRange.begin());
   // Lower the PTU
   if (llvm::Error Err = Interp->Execute(PTU)) {
@@ -276,6 +310,10 @@
 #else
 TEST(IncrementalProcessing, InstantiateTemplate) {
 #endif
+  // We cannot execute on the platform.
+  if (!HostSupportsJit())
+return;
+
   // FIXME: We cannot yet handle delayed template parsing. If we run with
   // -fdelayed-template-parsing we try adding the newly created decl to the
   // active PTU which causes an assert.
@@ -292,11 +330,6 @@
   auto PTUDeclRange = PTU.TUPart->decls();
   EXPECT_EQ(1, std::distance(PTUDeclRange.begin(), PTUDeclRange.end()));
 
-  // We cannot execute on the platform.
-  if (!HostSupportsJit()) {
-return;
-  }
-
   // Lower the PTU
   if (llvm::Error Err = Interp->Execute(PTU)) {
 // We cannot execute on the platform.
Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-16 Thread Jun Zhang via Phabricator via cfe-commits
junaire added a comment.

Because I have edited the commit messages several times so I forgot to include 
the revision link. Sorry. I have landed it as 
https://reviews.llvm.org/rGa423b7f1d7ca8b263af85944f57a69aa08fc942c


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D148997: [clang] Add a new annotation token: annot_repl_input_end

2023-05-16 Thread Jun Zhang via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG247fa04116a6: [clang] Add a new annotation token: 
annot_repl_input_end (authored by junaire).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148997

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Parse/Parser.h
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp

Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -320,6 +320,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Stop before we change submodules. They generally indicate a "good"
   // place to pick up parsing again (except in the special case where
   // we're trying to skip to EOF).
@@ -614,11 +615,6 @@
Sema::ModuleImportState ) {
   DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);
 
-  // Skip over the EOF token, flagging end of previous input for incremental
-  // processing
-  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
-ConsumeToken();
-
   Result = nullptr;
   switch (Tok.getKind()) {
   case tok::annot_pragma_unused:
@@ -697,6 +693,7 @@
 return false;
 
   case tok::eof:
+  case tok::annot_repl_input_end:
 // Check whether -fmax-tokens= was reached.
 if (PP.getMaxTokens() != 0 && PP.getTokenCount() > PP.getMaxTokens()) {
   PP.Diag(Tok.getLocation(), diag::warn_max_tokens_total)
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -544,9 +544,22 @@
 return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
   }
 
-  // Otherwise, eat the semicolon.
-  ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
-  return handleExprStmt(Expr, StmtCtx);
+  Token *CurTok = nullptr;
+  // If the semicolon is missing at the end of REPL input, consider if
+  // we want to do value printing. Note this is only enabled in C++ mode
+  // since part of the implementation requires C++ language features.
+  // Note we shouldn't eat the token since the callback needs it.
+  if (Tok.is(tok::annot_repl_input_end) && Actions.getLangOpts().CPlusPlus)
+CurTok = 
+  else
+// Otherwise, eat the semicolon.
+ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+
+  StmtResult R = handleExprStmt(Expr, StmtCtx);
+  if (CurTok && !R.isInvalid())
+CurTok->setAnnotationValue(R.get());
+
+  return R;
 }
 
 /// ParseSEHTryBlockCommon
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2070,6 +2070,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   return;
 
 default:
@@ -5456,6 +5457,13 @@
 
   SmallVector DeclsInGroup;
   DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get()));
+
+  if (Tok.is(tok::annot_repl_input_end) &&
+  Tok.getAnnotationValue() != nullptr) {
+ConsumeAnnotationToken();
+cast(DeclsInGroup.back())->setSemiMissing();
+  }
+
   // Currently happens for things like  -fms-extensions and use `__if_exists`.
   for (Stmt *S : Stmts)
 DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S));
Index: clang/lib/Parse/ParseCXXInlineMethods.cpp
===
--- clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -838,6 +838,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of tokens.
   return false;
 
@@ -1244,6 +1245,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of tokens.
   return false;
 
Index: clang/lib/Lex/PPLexerChange.cpp
===
--- clang/lib/Lex/PPLexerChange.cpp
+++ clang/lib/Lex/PPLexerChange.cpp
@@ -535,13 +535,19 @@
   return LeavingSubmodule;
 }
   }
-
   // If this is the end of the main file, form an EOF token.
   assert(CurLexer && "Got EOF but no current lexer set!");
   const char *EndPos = getCurLexerEndPos();
   Result.startToken();
   CurLexer->BufferPtr = EndPos;
-  

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-16 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 522545.
junaire added a comment.

remove whitespace


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,95 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_TRUE(V1.hasValue());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_EQ(V1.convertTo(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_TRUE(V2.hasValue());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_EQ(V2.convertTo(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.hasValue());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_FALSE(V6.hasValue());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.hasValue());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.hasValue());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V8.isManuallyAlloc());
+
+  Value V9;
+  

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-16 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 522530.
junaire added a comment.

Address comment from Vassil, thx


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,95 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_TRUE(V1.hasValue());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_EQ(V1.convertTo(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_TRUE(V2.hasValue());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_EQ(V2.convertTo(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.hasValue());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_FALSE(V6.hasValue());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.hasValue());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.hasValue());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V8.isManuallyAlloc());
+
+  Value V9;
+  

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-16 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 522527.
junaire added a comment.

Add comments


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,95 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_TRUE(V1.hasValue());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_EQ(V1.convertTo(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_TRUE(V2.hasValue());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_EQ(V2.convertTo(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.hasValue());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_FALSE(V6.hasValue());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.hasValue());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.hasValue());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V8.isManuallyAlloc());
+
+  Value V9;
+  

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-14 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 521985.
junaire added a comment.

Make and use our own std::void_t


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt

Index: clang/tools/clang-repl/CMakeLists.txt
===
--- clang/tools/clang-repl/CMakeLists.txt
+++ clang/tools/clang-repl/CMakeLists.txt
@@ -11,6 +11,65 @@
   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@std@@3Unothrow_t@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@YAPEAX_K@Z
+  ??3@YAXPEAX@Z
+  ??_U@YAPEAX_K@Z
+  ??_V@YAXPEAX@Z
+  ??3@YAXPEAX_K@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@PEBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@P6AAEAV01@AEAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z
+  ?_Facet_Register@std@@YAXPEAV_Facet_base@1@@Z
+)
+  else()
+set(clang_repl_exports ${clang_repl_exports}
+  ??2@YAPAXI@Z
+  ??3@YAXPAX@Z
+  ??3@YAXPAXI@Z
+  ??_U@YAPAXI@Z
+  ??_V@YAXPAX@Z
+  ??_V@YAXPAXI@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@PBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z
+  ?_Facet_Register@std@@YAXPAV_Facet_base@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
Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,180 @@
+// 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 -fno-delayed-template-parsing | FileCheck %s
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-14 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 521981.
junaire added a comment.

- include  to avoid incorrect lookup on Windows
- Add `-Xcc -fno-delayed-template-parsing` to fix failure on Windows


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt

Index: clang/tools/clang-repl/CMakeLists.txt
===
--- clang/tools/clang-repl/CMakeLists.txt
+++ clang/tools/clang-repl/CMakeLists.txt
@@ -11,6 +11,65 @@
   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@std@@3Unothrow_t@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@YAPEAX_K@Z
+  ??3@YAXPEAX@Z
+  ??_U@YAPEAX_K@Z
+  ??_V@YAXPEAX@Z
+  ??3@YAXPEAX_K@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@PEBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@P6AAEAV01@AEAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z
+  ?_Facet_Register@std@@YAXPEAV_Facet_base@1@@Z
+)
+  else()
+set(clang_repl_exports ${clang_repl_exports}
+  ??2@YAPAXI@Z
+  ??3@YAXPAX@Z
+  ??3@YAXPAXI@Z
+  ??_U@YAPAXI@Z
+  ??_V@YAXPAX@Z
+  ??_V@YAXPAXI@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@PBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z
+  ?_Facet_Register@std@@YAXPAV_Facet_base@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
Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,180 @@
+// 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 -fno-delayed-template-parsing | FileCheck %s
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-13 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 521962.
junaire added a comment.

Add macro guard.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt

Index: clang/tools/clang-repl/CMakeLists.txt
===
--- clang/tools/clang-repl/CMakeLists.txt
+++ clang/tools/clang-repl/CMakeLists.txt
@@ -11,6 +11,65 @@
   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@std@@3Unothrow_t@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@YAPEAX_K@Z
+  ??3@YAXPEAX@Z
+  ??_U@YAPEAX_K@Z
+  ??_V@YAXPEAX@Z
+  ??3@YAXPEAX_K@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@PEBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@P6AAEAV01@AEAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z
+  ?_Facet_Register@std@@YAXPEAV_Facet_base@1@@Z
+)
+  else()
+set(clang_repl_exports ${clang_repl_exports}
+  ??2@YAPAXI@Z
+  ??3@YAXPAX@Z
+  ??3@YAXPAXI@Z
+  ??_U@YAPAXI@Z
+  ??_V@YAXPAX@Z
+  ??_V@YAXPAXI@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@PBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z
+  ?_Facet_Register@std@@YAXPAV_Facet_base@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
Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,180 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+
+struct S3 { 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-13 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 521961.
junaire added a comment.

Don't use C++17 because Clang on Windows is not default to that :(


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt

Index: clang/tools/clang-repl/CMakeLists.txt
===
--- clang/tools/clang-repl/CMakeLists.txt
+++ clang/tools/clang-repl/CMakeLists.txt
@@ -11,6 +11,65 @@
   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@std@@3Unothrow_t@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@YAPEAX_K@Z
+  ??3@YAXPEAX@Z
+  ??_U@YAPEAX_K@Z
+  ??_V@YAXPEAX@Z
+  ??3@YAXPEAX_K@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@PEBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@P6AAEAV01@AEAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z
+  ?_Facet_Register@std@@YAXPEAV_Facet_base@1@@Z
+)
+  else()
+set(clang_repl_exports ${clang_repl_exports}
+  ??2@YAPAXI@Z
+  ??3@YAXPAX@Z
+  ??3@YAXPAXI@Z
+  ??_U@YAPAXI@Z
+  ??_V@YAXPAX@Z
+  ??_V@YAXPAXI@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@PBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z
+  ?_Facet_Register@std@@YAXPAV_Facet_base@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
Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,180 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-12 Thread Jun Zhang via Phabricator via cfe-commits
junaire marked 10 inline comments as done.
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Value.h:160-162
+  // Interpreter, QualType are stored as void* to reduce dependencies.
+  void *Interp = nullptr;
+  void *OpaqueType = nullptr;

v.g.vassilev wrote:
> sgraenitz wrote:
> > v.g.vassilev wrote:
> > > aaron.ballman wrote:
> > > > junaire wrote:
> > > > > aaron.ballman wrote:
> > > > > > v.g.vassilev wrote:
> > > > > > > aaron.ballman wrote:
> > > > > > > > v.g.vassilev wrote:
> > > > > > > > > aaron.ballman wrote:
> > > > > > > > > > Why don't forward declares suffice if we're storing the 
> > > > > > > > > > information by pointer?
> > > > > > > > > This is a performance-critical class. We literally measure 
> > > > > > > > > the instruction count for it. We practically cannot include 
> > > > > > > > > anything in this header file because the class needs to 
> > > > > > > > > included as part of the interpreter runtime. For example:
> > > > > > > > > 
> > > > > > > > > ```
> > > > > > > > > #include 
> > > > > > > > > Value ResultV;
> > > > > > > > > gInterpreter->evaluate("float i = 12.3; i++", );
> > > > > > > > > printf("Value is %d\n", ResultV.castAs());
> > > > > > > > > ```
> > > > > > > > > 
> > > > > > > > > This is how you can do things in Cling. This not yet there 
> > > > > > > > > but that's our next step.
> > > > > > > > > 
> > > > > > > > > For performance reasons we have the `ValueKind` optimization 
> > > > > > > > > which allows us to perform most of the operations we need 
> > > > > > > > > very fast. There are some operations such as printing the 
> > > > > > > > > concrete type which need the actual `QualType` and so on but 
> > > > > > > > > they are outside of the performance critical paths and it is 
> > > > > > > > > okay to resort back to the real types providing the level of 
> > > > > > > > > accuracy we need.
> > > > > > > > > 
> > > > > > > > That sounds like it's going to lead to maintenance problems in 
> > > > > > > > the long term, right? I can't think of another header file we 
> > > > > > > > say "don't touch this because it may impact runtime 
> > > > > > > > performance", and so I can easily imagine someone breaking your 
> > > > > > > > expectation that this file can't include anything else.
> > > > > > > > 
> > > > > > > > Is there a long-term plan for addressing this?
> > > > > > > We have a few components like the Lexer that are extremely prone 
> > > > > > > to performance regressions.
> > > > > > > 
> > > > > > > In terms for a longer-term plan in addressing this there are some 
> > > > > > > steps could help IMO. First, this component is relatively 
> > > > > > > standalone and very few changes will be required over time, for 
> > > > > > > these I am hoping to be listed as a reviewer. Second, we can add 
> > > > > > > a comment in the include area, making a note that including 
> > > > > > > anything here will degrade the performance of almost all 
> > > > > > > interpreted code. Third, we will find out about this in our 
> > > > > > > downstream use-cases as the things get significantly slower.
> > > > > > > 
> > > > > > > Neither is silver bullet but that's probably the best we could do 
> > > > > > > at that time. Btw, we might be able to add a test that's part of 
> > > > > > > LLVM's performance analysis infrastructure.
> > > > > > > Neither is silver bullet but that's probably the best we could do 
> > > > > > > at that time. Btw, we might be able to add a test that's part of 
> > > > > > > LLVM's performance analysis infrastructure.
> > > > > > 
> > > > > > Yeah, we should probably consider doing that. But to make sure I 
> > > > > > understand the performance concerns... when we change functionality 
> > > > > > in the lexer, we (potentially) slow down the lexing phase of 
> > > > > > compilation. That's straightforward and unsurprising. But in this 
> > > > > > case, it sounds like the act of including another header file in 
> > > > > > this header file will cause a runtime performance concern, even if 
> > > > > > no other changes are made. If I'm correct, I can't think of 
> > > > > > anything else in the compiler that works like that.
> > > > > I believe what @v.g.vassilev means is that the repl itself might 
> > > > > include `Value.h` as a part of *runtime*, so if the header is heavy, 
> > > > > you can notice the repl is slowed down. (That's obvious) So keep in 
> > > > > mind we're breaking the boundary between the compiled code and 
> > > > > interpreted code (It's kinda confusing) here it actually impacts 
> > > > > interpreted code.
> > > > > I believe what @v.g.vassilev means is that the repl itself might 
> > > > > include Value.h as a part of *runtime*, so if the header is heavy, 
> > > > > you can notice the repl is slowed down. (That's obvious) So keep in 
> > > > > mind we're breaking the boundary between the compiled code and 
> > > > > interpreted code (It's kinda 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-10 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 520998.
junaire added a comment.

Export symbols in Windows.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp
  clang/tools/clang-repl/CMakeLists.txt

Index: clang/tools/clang-repl/CMakeLists.txt
===
--- clang/tools/clang-repl/CMakeLists.txt
+++ clang/tools/clang-repl/CMakeLists.txt
@@ -11,6 +11,65 @@
   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@std@@3Unothrow_t@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@YAPEAX_K@Z
+  ??3@YAXPEAX@Z
+  ??_U@YAPEAX_K@Z
+  ??_V@YAXPEAX@Z
+  ??3@YAXPEAX_K@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@PEBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@P6AAEAV01@AEAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z
+  ?_Facet_Register@std@@YAXPEAV_Facet_base@1@@Z
+)
+  else()
+set(clang_repl_exports ${clang_repl_exports}
+  ??2@YAPAXI@Z
+  ??3@YAXPAX@Z
+  ??3@YAXPAXI@Z
+  ??_U@YAPAXI@Z
+  ??_V@YAXPAX@Z
+  ??_V@YAXPAXI@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@M@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@N@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@PBX@Z
+  ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@D@Z
+  ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z
+  ?_Facet_Register@std@@YAXPAV_Facet_base@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
Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,180 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-10 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 520914.
junaire added a comment.

Add some comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,180 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+
+struct S3 { int* p; S3() { p = new int(42); } ~S3() { delete p; } };
+S3{}
+// CHECK-NEXT: (S3) [[Addr:@0x.*]]
+S3 s3;
+s3
+// CHECK-NEXT: (S3 &) [[Addr:@0x.*]]
+
+struct S4 { ~S4() { printf("~S4()\n"); }};
+S4{}
+// CHECK-NEXT: (S4) [[Addr:@0x.*]]
+
+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
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+auto Lambda1 = []{};
+Lambda1
+// CHECK-NEXT: ((lambda) &) [[Addr:@0x.*]]
+[]{}
+// CHECK-NEXT: ((lambda at input_line_84:1:1)) [[Addr:@0x.*]]
+
+template struct F{ enum {RET=F::RET*n} ; };
+template<> struct F<0> { enum {RET = 1}; };
+F<7>::RET
+// CHECK-NEXT: (F<7>::(unnamed enum at input_line_87: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; }};
+::foo
+// CHECK-NEXT: (int (S5::*)()) Function [[Addr:@0x.*]]
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (std::shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+auto p2 = std::make_unique(42);
+p2
+// CHECK-NEXT: (std::unique_ptr > &) std::unique_ptr -> [[Addr:@0x.*]]
+
+#include 
+std::array a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array &) { 1, 2, 3 }
+
+#include 
+std::vector v1 = {7, 5, 16, 8};
+v1
+// CHECK-NEXT: (std::vector &) { 7, 5, 16, 8 }
+
+std::vector v = {true, false, true};
+v
+// CHECK-NEXT: (std::vector &) { true, false, true }
+
+#include 
+std::deque dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque &) { 7, 5, 16, 8 }
+
+#include 
+std::forward_list fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list &) { 3, 4, 5, 6 }
+
+#include 
+std::set z1 = {2,4,6,8};
+z1
+// CHECK-NEXT: (std::set &) { 2, 4, 6, 8 }
+
+#include 
+std::unordered_set z2 = {8,2,4,6};
+z2
+// CHECK-NEXT: (std::unordered_set &) { 6, 4, 2, 8 }
+
+std::multiset e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset &) { 1, 2, 2, 3, 3, 4, 7 }
+
+#include 
+std::string std_str = "Hello, world!";
+std_str
+// CHECK-NEXT: (std::string &) "Hello, world!"
+
+#include 
+std::pair pr(42,'a');
+pr
+// CHECK-NEXT: (std::pair &) { 42, 'a' }
+
+#include 
+std::tuple tu(42,3.14,'a');
+tu
+// CHECK-NEXT: (std::tuple &) { 42, 3.140, 'a' }
+
+#include 
+std::map m1{{"CPU", 10}, {"GPU", 15}, {"RAM", 20}};
+m1
+// CHECK-NEXT: (std::map &) { "CPU" => 10, "GPU" => 15, "RAM" => 20 }
+
+#include 
+std::unordered_map m2 = { {"RED","#FF"}, {"GREEN","#00FF00"}};
+m2
+// CHECK-NEXT: (std::unordered_map &) { "GREEN" => "#00FF00", "RED" => "#FF" }
+
+struct MyType {};
+std::string PrintValueRuntime(const MyType*) { return "My pretty printer!"; }
+MyType{}
+// CHECK-NEXT: (MyType) My pretty printer!
+%quit
+
Index: 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-10 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 520913.
junaire added a comment.

Remove unused code.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,180 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+
+struct S3 { int* p; S3() { p = new int(42); } ~S3() { delete p; } };
+S3{}
+// CHECK-NEXT: (S3) [[Addr:@0x.*]]
+S3 s3;
+s3
+// CHECK-NEXT: (S3 &) [[Addr:@0x.*]]
+
+struct S4 { ~S4() { printf("~S4()\n"); }};
+S4{}
+// CHECK-NEXT: (S4) [[Addr:@0x.*]]
+
+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
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+auto Lambda1 = []{};
+Lambda1
+// CHECK-NEXT: ((lambda) &) [[Addr:@0x.*]]
+[]{}
+// CHECK-NEXT: ((lambda at input_line_84:1:1)) [[Addr:@0x.*]]
+
+template struct F{ enum {RET=F::RET*n} ; };
+template<> struct F<0> { enum {RET = 1}; };
+F<7>::RET
+// CHECK-NEXT: (F<7>::(unnamed enum at input_line_87: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; }};
+::foo
+// CHECK-NEXT: (int (S5::*)()) Function [[Addr:@0x.*]]
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (std::shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+auto p2 = std::make_unique(42);
+p2
+// CHECK-NEXT: (std::unique_ptr > &) std::unique_ptr -> [[Addr:@0x.*]]
+
+#include 
+std::array a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array &) { 1, 2, 3 }
+
+#include 
+std::vector v1 = {7, 5, 16, 8};
+v1
+// CHECK-NEXT: (std::vector &) { 7, 5, 16, 8 }
+
+std::vector v = {true, false, true};
+v
+// CHECK-NEXT: (std::vector &) { true, false, true }
+
+#include 
+std::deque dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque &) { 7, 5, 16, 8 }
+
+#include 
+std::forward_list fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list &) { 3, 4, 5, 6 }
+
+#include 
+std::set z1 = {2,4,6,8};
+z1
+// CHECK-NEXT: (std::set &) { 2, 4, 6, 8 }
+
+#include 
+std::unordered_set z2 = {8,2,4,6};
+z2
+// CHECK-NEXT: (std::unordered_set &) { 6, 4, 2, 8 }
+
+std::multiset e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset &) { 1, 2, 2, 3, 3, 4, 7 }
+
+#include 
+std::string std_str = "Hello, world!";
+std_str
+// CHECK-NEXT: (std::string &) "Hello, world!"
+
+#include 
+std::pair pr(42,'a');
+pr
+// CHECK-NEXT: (std::pair &) { 42, 'a' }
+
+#include 
+std::tuple tu(42,3.14,'a');
+tu
+// CHECK-NEXT: (std::tuple &) { 42, 3.140, 'a' }
+
+#include 
+std::map m1{{"CPU", 10}, {"GPU", 15}, {"RAM", 20}};
+m1
+// CHECK-NEXT: (std::map &) { "CPU" => 10, "GPU" => 15, "RAM" => 20 }
+
+#include 
+std::unordered_map m2 = { {"RED","#FF"}, {"GREEN","#00FF00"}};
+m2
+// CHECK-NEXT: (std::unordered_map &) { "GREEN" => "#00FF00", "RED" => "#FF" }
+
+struct MyType {};
+std::string PrintValueRuntime(const MyType*) { return "My pretty printer!"; }
+MyType{}
+// CHECK-NEXT: (MyType) My pretty printer!
+%quit
+
Index: 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-10 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 520912.
junaire added a comment.

Fix


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,180 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+
+struct S3 { int* p; S3() { p = new int(42); } ~S3() { delete p; } };
+S3{}
+// CHECK-NEXT: (S3) [[Addr:@0x.*]]
+S3 s3;
+s3
+// CHECK-NEXT: (S3 &) [[Addr:@0x.*]]
+
+struct S4 { ~S4() { printf("~S4()\n"); }};
+S4{}
+// CHECK-NEXT: (S4) [[Addr:@0x.*]]
+
+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
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+auto Lambda1 = []{};
+Lambda1
+// CHECK-NEXT: ((lambda) &) [[Addr:@0x.*]]
+[]{}
+// CHECK-NEXT: ((lambda at input_line_84:1:1)) [[Addr:@0x.*]]
+
+template struct F{ enum {RET=F::RET*n} ; };
+template<> struct F<0> { enum {RET = 1}; };
+F<7>::RET
+// CHECK-NEXT: (F<7>::(unnamed enum at input_line_87: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; }};
+::foo
+// CHECK-NEXT: (int (S5::*)()) Function [[Addr:@0x.*]]
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (std::shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+auto p2 = std::make_unique(42);
+p2
+// CHECK-NEXT: (std::unique_ptr > &) std::unique_ptr -> [[Addr:@0x.*]]
+
+#include 
+std::array a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array &) { 1, 2, 3 }
+
+#include 
+std::vector v1 = {7, 5, 16, 8};
+v1
+// CHECK-NEXT: (std::vector &) { 7, 5, 16, 8 }
+
+std::vector v = {true, false, true};
+v
+// CHECK-NEXT: (std::vector &) { true, false, true }
+
+#include 
+std::deque dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque &) { 7, 5, 16, 8 }
+
+#include 
+std::forward_list fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list &) { 3, 4, 5, 6 }
+
+#include 
+std::set z1 = {2,4,6,8};
+z1
+// CHECK-NEXT: (std::set &) { 2, 4, 6, 8 }
+
+#include 
+std::unordered_set z2 = {8,2,4,6};
+z2
+// CHECK-NEXT: (std::unordered_set &) { 6, 4, 2, 8 }
+
+std::multiset e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset &) { 1, 2, 2, 3, 3, 4, 7 }
+
+#include 
+std::string std_str = "Hello, world!";
+std_str
+// CHECK-NEXT: (std::string &) "Hello, world!"
+
+#include 
+std::pair pr(42,'a');
+pr
+// CHECK-NEXT: (std::pair &) { 42, 'a' }
+
+#include 
+std::tuple tu(42,3.14,'a');
+tu
+// CHECK-NEXT: (std::tuple &) { 42, 3.140, 'a' }
+
+#include 
+std::map m1{{"CPU", 10}, {"GPU", 15}, {"RAM", 20}};
+m1
+// CHECK-NEXT: (std::map &) { "CPU" => 10, "GPU" => 15, "RAM" => 20 }
+
+#include 
+std::unordered_map m2 = { {"RED","#FF"}, {"GREEN","#00FF00"}};
+m2
+// CHECK-NEXT: (std::unordered_map &) { "GREEN" => "#00FF00", "RED" => "#FF" }
+
+struct MyType {};
+std::string PrintValueRuntime(const MyType*) { return "My pretty printer!"; }
+MyType{}
+// CHECK-NEXT: (MyType) My pretty printer!
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-08 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 520326.
junaire marked an inline comment as done.
junaire added a comment.

.


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,95 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_TRUE(V1.hasValue());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_EQ(V1.convertTo(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_TRUE(V2.hasValue());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_EQ(V2.convertTo(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.hasValue());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_FALSE(V6.hasValue());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.hasValue());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.hasValue());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V8.isManuallyAlloc());
+
+  Value V9;

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-08 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 520324.
junaire added a comment.

Rebase + Update


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Parse/Parser.h
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp

Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -320,6 +320,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Stop before we change submodules. They generally indicate a "good"
   // place to pick up parsing again (except in the special case where
   // we're trying to skip to EOF).
@@ -614,11 +615,6 @@
Sema::ModuleImportState ) {
   DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);
 
-  // Skip over the EOF token, flagging end of previous input for incremental
-  // processing
-  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
-ConsumeToken();
-
   Result = nullptr;
   switch (Tok.getKind()) {
   case tok::annot_pragma_unused:
@@ -697,6 +693,7 @@
 return false;
 
   case tok::eof:
+  case tok::annot_repl_input_end:
 // Check whether -fmax-tokens= was reached.
 if (PP.getMaxTokens() != 0 && PP.getTokenCount() > PP.getMaxTokens()) {
   PP.Diag(Tok.getLocation(), diag::warn_max_tokens_total)
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -544,9 +544,22 @@
 return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
   }
 
-  // Otherwise, eat the semicolon.
-  ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
-  return handleExprStmt(Expr, StmtCtx);
+  Token *CurTok = nullptr;
+  // If the semicolon is missing at the end of REPL input, consider if
+  // we want to do value printing. Note this is only enabled in C++ mode
+  // since part of the implementation requires C++ language features.
+  // Note we shouldn't eat the token since the callback needs it.
+  if (Tok.is(tok::annot_repl_input_end) && Actions.getLangOpts().CPlusPlus)
+CurTok = 
+  else
+// Otherwise, eat the semicolon.
+ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+
+  StmtResult R = handleExprStmt(Expr, StmtCtx);
+  if (CurTok && !R.isInvalid())
+CurTok->setAnnotationValue(R.get());
+
+  return R;
 }
 
 /// ParseSEHTryBlockCommon
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2070,6 +2070,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   return;
 
 default:
@@ -5454,6 +5455,13 @@
 
   SmallVector DeclsInGroup;
   DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get()));
+
+  if (Tok.is(tok::annot_repl_input_end) &&
+  Tok.getAnnotationValue() != nullptr) {
+ConsumeAnnotationToken();
+cast(DeclsInGroup.back())->setSemiMissing();
+  }
+
   // Currently happens for things like  -fms-extensions and use `__if_exists`.
   for (Stmt *S : Stmts)
 DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S));
Index: clang/lib/Parse/ParseCXXInlineMethods.cpp
===
--- clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -838,6 +838,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of tokens.
   return false;
 
@@ -1244,6 +1245,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of tokens.
   return false;
 
Index: clang/lib/Lex/PPLexerChange.cpp
===
--- clang/lib/Lex/PPLexerChange.cpp
+++ clang/lib/Lex/PPLexerChange.cpp
@@ -535,13 +535,19 @@
   return LeavingSubmodule;
 }
   }
-
   // If this is the end of the main file, form an EOF token.
   assert(CurLexer && "Got EOF but no current lexer set!");
   const char *EndPos = getCurLexerEndPos();
   Result.startToken();
   CurLexer->BufferPtr = EndPos;
-  CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
+
+  if (isIncrementalProcessingEnabled()) {
+

[PATCH] D148997: [clang] Add a new annotation token: annot_repl_input_end

2023-05-08 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 520313.
junaire added a comment.

Update + Rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148997

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Parse/Parser.h
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp

Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -320,6 +320,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Stop before we change submodules. They generally indicate a "good"
   // place to pick up parsing again (except in the special case where
   // we're trying to skip to EOF).
@@ -614,11 +615,6 @@
Sema::ModuleImportState ) {
   DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);
 
-  // Skip over the EOF token, flagging end of previous input for incremental
-  // processing
-  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
-ConsumeToken();
-
   Result = nullptr;
   switch (Tok.getKind()) {
   case tok::annot_pragma_unused:
@@ -697,6 +693,7 @@
 return false;
 
   case tok::eof:
+  case tok::annot_repl_input_end:
 // Check whether -fmax-tokens= was reached.
 if (PP.getMaxTokens() != 0 && PP.getTokenCount() > PP.getMaxTokens()) {
   PP.Diag(Tok.getLocation(), diag::warn_max_tokens_total)
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -544,9 +544,22 @@
 return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
   }
 
-  // Otherwise, eat the semicolon.
-  ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
-  return handleExprStmt(Expr, StmtCtx);
+  Token *CurTok = nullptr;
+  // If the semicolon is missing at the end of REPL input, consider if
+  // we want to do value printing. Note this is only enabled in C++ mode
+  // since part of the implementation requires C++ language features.
+  // Note we shouldn't eat the token since the callback needs it.
+  if (Tok.is(tok::annot_repl_input_end) && Actions.getLangOpts().CPlusPlus)
+CurTok = 
+  else
+// Otherwise, eat the semicolon.
+ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+
+  StmtResult R = handleExprStmt(Expr, StmtCtx);
+  if (CurTok && !R.isInvalid())
+CurTok->setAnnotationValue(R.get());
+
+  return R;
 }
 
 /// ParseSEHTryBlockCommon
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2070,6 +2070,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   return;
 
 default:
@@ -5454,6 +5455,13 @@
 
   SmallVector DeclsInGroup;
   DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get()));
+
+  if (Tok.is(tok::annot_repl_input_end) &&
+  Tok.getAnnotationValue() != nullptr) {
+ConsumeAnnotationToken();
+cast(DeclsInGroup.back())->setSemiMissing();
+  }
+
   // Currently happens for things like  -fms-extensions and use `__if_exists`.
   for (Stmt *S : Stmts)
 DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S));
Index: clang/lib/Parse/ParseCXXInlineMethods.cpp
===
--- clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -838,6 +838,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of tokens.
   return false;
 
@@ -1244,6 +1245,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of tokens.
   return false;
 
Index: clang/lib/Lex/PPLexerChange.cpp
===
--- clang/lib/Lex/PPLexerChange.cpp
+++ clang/lib/Lex/PPLexerChange.cpp
@@ -535,13 +535,19 @@
   return LeavingSubmodule;
 }
   }
-
   // If this is the end of the main file, form an EOF token.
   assert(CurLexer && "Got EOF but no current lexer set!");
   const char *EndPos = getCurLexerEndPos();
   Result.startToken();
   CurLexer->BufferPtr = EndPos;
-  CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
+
+  if (isIncrementalProcessingEnabled()) {
+

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-02 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518961.
junaire added a comment.

Fix typos


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,95 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_TRUE(V1.hasValue());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_EQ(V1.convertTo(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_TRUE(V2.hasValue());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_EQ(V2.convertTo(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.hasValue());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_FALSE(V6.hasValue());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.hasValue());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.hasValue());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V8.isManuallyAlloc());
+
+  Value V9;
+  

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-02 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Interpreter.h:59
+
+  Value LastValue;
 

v.g.vassilev wrote:
> aaron.ballman wrote:
> > I think I'm surprised to see this as a data member of `Interpreter` but 
> > mostly because my brain keeps thinking this interpreter is to interpret 
> > whole programs, so the idea of a "last value" is a bit odd from that 
> > context. The name is probably fine as-is, but I figured it may be worth 
> > mentioning just the same.
> One way to think of this is every `repl` has some way to access the last 
> result it created when executed its last chunk of input. In python that's the 
> `_` value. In the debugger it is the `%N` where N is some number. Here this 
> variable would enable implementing a similar to these in future.
I added some comments.



Comment at: clang/include/clang/Interpreter/Value.h:83
+  Value() = default;
+  Value(void /*Interpreter*/ *In, void /*QualType*/ *Ty);
+  Value(const Value );

aaron.ballman wrote:
> junaire wrote:
> > aaron.ballman wrote:
> > > v.g.vassilev wrote:
> > > > junaire wrote:
> > > > > aaron.ballman wrote:
> > > > > > Why do these take `void *` instead of the expected type?
> > > > > Yeah for the first parameter, we could just use `Interpreter*` but 
> > > > > the second one is an opaque type so I think we should keep it?
> > > > See my previous comments on performance. We cannot include anything 
> > > > bulky in the header file.
> > > I think I understand why the design is the way it is, but it still makes 
> > > me uneasy. The constructor takes a pointer to some bucket of bytes... no 
> > > size information, no type information, etc. Just "here's a random 
> > > pointer". And then later, we hope the user calls `setKind()` in a way 
> > > that makes sense.
> > > 
> > > We need it to be fast, but we also need it to be correct -- the type 
> > > system is the best tool for helping with that.
> > Not really... The user doesn't need to call `setKind()` explicitly to 
> > construct a `Value`, the constructor will handle it automatically. See 
> > `ConvertQualTypeToKind` in `Value.cpp`. So if the pointer is just some 
> > garbage data, the constructor should fail before yielding out a valid 
> > instance.
> Yeah, that's a fair point, except nothing actually validates that the opaque 
> pointer you are handed is actually valid for anything because it eventually 
> just does a reinterpret_cast, so I don't think the constructor will fail.
OK, let me try to answer why we're passing `QualType` in an opaque pointer way. 
So the `Value` is *constructed* in `__clang_Interpreter_SetValue*` variants, 
and these functions (let's call them runtime interfaces) are synthesized when 
we want to do value printing (like we have a `x` without semi). So it makes 
things pretty hard if we use a complete type (How can we synthesize that type? 
That dramatically complicated the code) In addition, we want `Value.h`, which 
is part of the runtime, as lightweight as possible, so we can't use the 
complete type in its constructor, or we have to include the corresponding 
header file.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-02 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518960.
junaire marked 2 inline comments as done.
junaire added a comment.

Add more comments.


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,95 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_TRUE(V1.hasValue());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_EQ(V1.convertTo(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_TRUE(V2.hasValue());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_EQ(V2.convertTo(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.hasValue());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_FALSE(V6.hasValue());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.hasValue());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.hasValue());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-02 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Value.h:46
+
+#define REPL_BUILTIN_TYPES 
\
+  X(bool, Bool)
\

aaron.ballman wrote:
> v.g.vassilev wrote:
> > aaron.ballman wrote:
> > > v.g.vassilev wrote:
> > > > aaron.ballman wrote:
> > > > > Is this expected to be a complete list of builtin types? e.g., should 
> > > > > this have `char8_t` and `void` and `wchar_t`, etc? Should this be 
> > > > > including `clang/include/clang/AST/BuiltinTypes.def` instead of 
> > > > > manually maintaining the list?
> > > > This is used for various things including storing the bits into a 
> > > > big-endian agnostic way. For `void` we have a special case in the Value 
> > > > and we cannot define a union of a `void` type. We can include the 
> > > > others that you suggest. All the relevant ones are described in 
> > > > `clang::BuiltinType::getName`.
> > > > 
> > > > We cannot use `BuiltinTypes.def` because we want to have a mapping 
> > > > between the type as written in the language (eg, `bool`, `unsigned`, 
> > > > etc) and its underlying type name. That mapping is not available in 
> > > > `BuiltinTypes.def`. Ideally we should extend `BuiltinTypes.def` somehow 
> > > > but I'd prefer outside of this patch. One of the challenges is that 
> > > > some of the types depend on the language options (eg. `_Bool` vs 
> > > > `bool`) and I am not sure this can be resolved by tablegen.
> > > > 
> > > > On a broader perspective, the `Value` class is responsible for two 
> > > > things: (a) get a value from the interpreter to compiled code (see test 
> > > > case); (b) set a value from compiled code to the interpreter. The 
> > > > second case is not yet covered (I can open soon another patch). The 
> > > > major use-case is calling at runtime functions and taking input 
> > > > parameters from compiled code.
> > > > 
> > > > FWIW, we should probably move all of these entities in a separate 
> > > > namespace. I'd suggest `caas` (compiler-as-a-service) and possibly 
> > > > rename the `Value` to `InterpreterValue` since `Value` is very generic 
> > > > and there are already a couple of classes with that name in llvm and 
> > > > clang. 
> > > > We can include the others that you suggest. All the relevant ones are 
> > > > described in clang::BuiltinType::getName.
> > > 
> > > Okay, so the plan is to handle all the builtin types (`_BitInt`, 
> > > `_Complex`, various floating point formats, etc)? Will that be part of 
> > > this patch or in follow-up work? (My intuition is that we should consider 
> > > it up front because some of the builtin types are interesting -- like 
> > > `_BitInt` because it's parameterized, which makes it novel compared to 
> > > the other types.)
> > > 
> > > > We cannot use BuiltinTypes.def because we want to have a mapping 
> > > > between the type as written in the language (eg, bool, unsigned, etc) 
> > > > and its underlying type name. That mapping is not available in 
> > > > BuiltinTypes.def. Ideally we should extend BuiltinTypes.def somehow but 
> > > > I'd prefer outside of this patch. One of the challenges is that some of 
> > > > the types depend on the language options (eg. _Bool vs bool) and I am 
> > > > not sure this can be resolved by tablegen.
> > > 
> > > Thanks for the explanation! BuiltinTypes.def works well enough for times 
> > > when we want to use macros and include the file to generate switch cases 
> > > and the likes, but you're right that it's not well-suited for this. One 
> > > thing to consider is whether we should change `BuiltinTypes.def` to be 
> > > `BuiltinTypes.td` instead and use tablegen to generate the macro/include 
> > > dance form as well as other output (such as for your needs, that can then 
> > > consider language options or more complex predicates).
> > > 
> > > > FWIW, we should probably move all of these entities in a separate 
> > > > namespace. I'd suggest caas (compiler-as-a-service) and possibly rename 
> > > > the Value to InterpreterValue since Value is very generic and there are 
> > > > already a couple of classes with that name in llvm and clang.
> > > 
> > > I'm not in love with the name `caas` because that's not really a common 
> > > acronym or abbreviation (and it looks like a typo due to `aa`). However, 
> > > we already have an `interp` namespace in Clang for one of the other 
> > > interpreters (constant expression evaluation), so that's not available 
> > > for use. How about `repl` though?
> > > 
> > > As for considering changing the name from `Value` because of how many 
> > > other `Value` types we have already... that's both a reason to rename and 
> > > reason not to rename. I think I'm fine leaving it as `Value` so long as 
> > > it's in a novel namespace.
> > > > We can include the others that you suggest. All the relevant ones are 
> > > > described 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-02 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518952.
junaire marked 16 inline comments as done.
junaire added a comment.

Address comments from @aaron.ballman, thanks!


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,95 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_TRUE(V1.hasValue());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_EQ(V1.convertTo(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_TRUE(V2.hasValue());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_EQ(V2.convertTo(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.hasValue());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_FALSE(V6.hasValue());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.hasValue());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.hasValue());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  

[PATCH] D148997: [clang] Add a new annotation token: annot_repl_input_end

2023-05-02 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/lib/Interpreter/IncrementalParser.cpp:162
+  if (P->getCurToken().is(tok::annot_repl_input_end)) {
+P->ConsumeAnyToken();
 // FIXME: Clang does not call ExitScope on finalizing the regular TU, we

rsmith wrote:
> 
Sorry but that's a private member function so I can't do that. Should I make it 
public?



Comment at: clang/lib/Parse/Parser.cpp:620-621
   // processing
-  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
-ConsumeToken();
+  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::annot_repl_input_end))
+ConsumeAnnotationToken();
 

rsmith wrote:
> Do we need to do this here? `IncrementalParser` already seems to take care of 
> this, and the logic here would be easier to reason about if `Parser` never 
> steps past an `annot_repl_input_end` token, and such tokens instead are only 
> ever consumed by the REPL.
> 
> Are there other users of incremental processing mode, other than the REPL / 
> `IncrementalParser`?
Make sense to me, I'll remove it.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148997

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D148997: [clang] Add a new annotation token: annot_repl_input_end

2023-05-02 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518738.
junaire marked 3 inline comments as done.
junaire added a comment.

Address comments, thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148997

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp

Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -320,6 +320,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Stop before we change submodules. They generally indicate a "good"
   // place to pick up parsing again (except in the special case where
   // we're trying to skip to EOF).
@@ -614,11 +615,6 @@
Sema::ModuleImportState ) {
   DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);
 
-  // Skip over the EOF token, flagging end of previous input for incremental
-  // processing
-  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
-ConsumeToken();
-
   Result = nullptr;
   switch (Tok.getKind()) {
   case tok::annot_pragma_unused:
@@ -697,6 +693,7 @@
 return false;
 
   case tok::eof:
+  case tok::annot_repl_input_end:
 // Check whether -fmax-tokens= was reached.
 if (PP.getMaxTokens() != 0 && PP.getTokenCount() > PP.getMaxTokens()) {
   PP.Diag(Tok.getLocation(), diag::warn_max_tokens_total)
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -543,9 +543,22 @@
 return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
   }
 
-  // Otherwise, eat the semicolon.
-  ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
-  return handleExprStmt(Expr, StmtCtx);
+  Token *CurTok = nullptr;
+  // If the semicolon is missing at the end of REPL input, consider if
+  // we want to do value printing. Note this is only enabled in C++ mode
+  // since part of the implementation requires C++ language features.
+  // Note we shouldn't eat the token since the callback needs it.
+  if (Tok.is(tok::annot_repl_input_end) && Actions.getLangOpts().CPlusPlus)
+CurTok = 
+  else
+// Otherwise, eat the semicolon.
+ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+
+  StmtResult R = handleExprStmt(Expr, StmtCtx);
+  if (CurTok && !R.isInvalid())
+CurTok->setAnnotationValue(R.get());
+
+  return R;
 }
 
 /// ParseSEHTryBlockCommon
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2069,6 +2069,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   return;
 
 default:
@@ -5453,6 +5454,13 @@
 
   SmallVector DeclsInGroup;
   DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get()));
+
+  if (Tok.is(tok::annot_repl_input_end) &&
+  Tok.getAnnotationValue() != nullptr) {
+ConsumeAnnotationToken();
+cast(DeclsInGroup.back())->setValuePrinting();
+  }
+
   // Currently happens for things like  -fms-extensions and use `__if_exists`.
   for (Stmt *S : Stmts)
 DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S));
Index: clang/lib/Parse/ParseCXXInlineMethods.cpp
===
--- clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -836,6 +836,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of tokens.
   return false;
 
@@ -1242,6 +1243,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of tokens.
   return false;
 
Index: clang/lib/Lex/PPLexerChange.cpp
===
--- clang/lib/Lex/PPLexerChange.cpp
+++ clang/lib/Lex/PPLexerChange.cpp
@@ -535,13 +535,19 @@
   return LeavingSubmodule;
 }
   }
-
   // If this is the end of the main file, form an EOF token.
   assert(CurLexer && "Got EOF but no current lexer set!");
   const char *EndPos = getCurLexerEndPos();
   Result.startToken();
   CurLexer->BufferPtr = EndPos;
-  CurLexer->FormTokenWithChars(Result, 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-01 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/test/Interpreter/pretty-print.cpp:107
+p2
+// CHECK-NEXT: (std::_MakeUniq::__single_object &) std::unique_ptr -> 
[[Addr:@0x.*]]
+

junaire wrote:
> Hi @mizvekov, do you have a clue about why it doesn't print the correct type? 
> So in `ValuePrinter.cpp:50` I dumped the type it shows:
> ```
> AutoType 0x62d000533c00 'typename _MakeUniq::__single_object' sugar
> `-ElaboratedType 0x62d000450500 'typename _MakeUniq::__single_object' 
> sugar
>   `-TypedefType 0x62d0004501e0 'std::_MakeUniq::__single_object' sugar
> |-Typedef 0x62d000450160 '__single_object'
> `-ElaboratedType 0x62d000450100 'unique_ptr' sugar
>   `-TemplateSpecializationType 0x62d0004500b0 'unique_ptr' sugar 
> unique_ptr
> |-TemplateArgument type 'int':'int'
> | `-SubstTemplateTypeParmType 0x62d00044fd50 'int' sugar typename 
> depth 0 index 0 _Tp
> |   |-ClassTemplateSpecialization 0x62d00044fa08 '_MakeUniq'
> |   `-BuiltinType 0x62119220 'int'
> `-RecordType 0x62d000450080 'class std::unique_ptr'
>   `-ClassTemplateSpecialization 0x62d00044ff70 'unique_ptr'
> ```
> 
> But in Cling it only has the RecordType. Do you think it's affected by your 
> type resugaring patches?
Looks like below diff fixes this:
```
diff --git a/clang/lib/Interpreter/InterpreterUtils.cpp 
b/clang/lib/Interpreter/InterpreterUtils.cpp
index 05e6be0e9df2..da5da55e8e95 100644
--- a/clang/lib/Interpreter/InterpreterUtils.cpp
+++ b/clang/lib/Interpreter/InterpreterUtils.cpp
@@ -425,7 +425,7 @@ QualType GetFullyQualifiedType(QualType QT, const 
ASTContext ) {
   // Strip deduced types.
   if (const auto *AutoTy = dyn_cast(QT.getTypePtr())) {
 if (!AutoTy->getDeducedType().isNull())
-  return GetFullyQualifiedType(AutoTy->getDeducedType(), Ctx);
+  return 
GetFullyQualifiedType(AutoTy->getDeducedType().getDesugaredType(Ctx), Ctx);
   }
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-05-01 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518458.
junaire added a comment.

Fix AutoType sugar


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,163 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+int x = 42;
+x
+// CHECK-NEXT: (int) 42
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+
+struct S3 { int* p; S3() { p = new int(42); } ~S3() { delete p; } };
+S3{}
+// CHECK-NEXT: (S3) [[Addr:@0x.*]]
+S3 s3;
+s3
+// CHECK-NEXT: (S3 &) [[Addr:@0x.*]]
+
+struct S4 { ~S4() { printf("~S4()\n"); }};
+S4{}
+// CHECK-NEXT: (S4) [[Addr:@0x.*]]
+
+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
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+auto Lambda1 = []{};
+Lambda1
+// CHECK-NEXT: ((lambda) &) [[Addr:@0x.*]]
+[]{}
+// CHECK-NEXT: ((lambda at input_line_81:1:1)) [[Addr:@0x.*]]
+
+template struct F{ enum {RET=F::RET*n} ; };
+template<> struct F<0> { enum {RET = 1}; };
+F<7>::RET
+// CHECK-NEXT: (F<7>::(unnamed enum at input_line_84: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; }};
+::foo
+// CHECK-NEXT: (int (S5::*)()) Function [[Addr:@0x.*]]
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (std::shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+auto p2 = std::make_unique(42);
+p2
+// CHECK-NEXT: (std::unique_ptr > &) std::unique_ptr -> [[Addr:@0x.*]]
+
+#include 
+std::array a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array &) { 1, 2, 3 }
+
+#include 
+std::vector v = {7, 5, 16, 8};
+v
+// CHECK-NEXT: (std::vector &) { 7, 5, 16, 8 }
+
+#include 
+std::deque dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque &) { 7, 5, 16, 8 }
+
+#include 
+std::forward_list fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list &) { 3, 4, 5, 6 }
+
+#include 
+std::set z = {2,4,6,8};
+z
+// CHECK-NEXT: (std::set &) { 2, 4, 6, 8 }
+
+std::multiset e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset &) { 1, 2, 2, 3, 3, 4, 7 }
+
+#include 
+std::string std_str = "Hello, world!";
+std_str
+// CHECK-NEXT: (std::string &) "Hello, world!"
+
+#include 
+std::pair pr(42,'a');
+pr
+// CHECK-NEXT: (std::pair &) { 42, 'a' }
+
+#include 
+std::tuple tu(42,3.14,'a');
+tu
+// CHECK-NEXT: (std::tuple &) { 42, 3.140, 'a' }
+
+#include 
+std::map m{{"CPU", 10}, {"GPU", 15}, {"RAM", 20}};
+m
+// CHECK-NEXT: (std::map &) { "CPU" => 10, "GPU" => 15, "RAM" => 20 }
+
+struct MyType {};
+std::string PrintValueRuntime(const MyType*) { return "My pretty printer!"; }
+MyType{}
+// CHECK-NEXT: (MyType) My pretty printer!
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,526 @@
+#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 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-01 Thread Jun Zhang via Phabricator via cfe-commits
junaire marked an inline comment as done.
junaire added inline comments.



Comment at: clang/lib/Interpreter/Interpreter.cpp:211
+void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long 
long);
+template 
+void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned 
long Size) {

v.g.vassilev wrote:
> Can you add an `#ifdef __cplusplus` and add a value printing tests that run 
> in clang-repl in C mode?
After a private chat, we decide to disable the feature in C mode because it 
sounds like a bad idea to give C incomplete value printing support.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-05-01 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518450.
junaire added a comment.

.


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,93 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_TRUE(V1.hasValue());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_TRUE(V2.hasValue());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.hasValue());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_FALSE(V6.hasValue());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.hasValue());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.hasValue());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V8.isManuallyAlloc());
+
+  Value V9;
+  llvm::cantFail(Interp->ParseAndExecute("struct A { virtual int f(); };"));
+  llvm::cantFail(
+  

[PATCH] D148997: [clang] Add a new annotation token: annot_repl_input_end

2023-05-01 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518448.
junaire added a comment.

.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148997

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp

Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -320,6 +320,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Stop before we change submodules. They generally indicate a "good"
   // place to pick up parsing again (except in the special case where
   // we're trying to skip to EOF).
@@ -616,8 +617,8 @@
 
   // Skip over the EOF token, flagging end of previous input for incremental
   // processing
-  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
-ConsumeToken();
+  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::annot_repl_input_end))
+ConsumeAnnotationToken();
 
   Result = nullptr;
   switch (Tok.getKind()) {
@@ -697,6 +698,7 @@
 return false;
 
   case tok::eof:
+  case tok::annot_repl_input_end:
 // Check whether -fmax-tokens= was reached.
 if (PP.getMaxTokens() != 0 && PP.getTokenCount() > PP.getMaxTokens()) {
   PP.Diag(Tok.getLocation(), diag::warn_max_tokens_total)
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -543,9 +543,25 @@
 return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
   }
 
-  // Otherwise, eat the semicolon.
-  ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
-  return handleExprStmt(Expr, StmtCtx);
+  Token *CurTok = nullptr;
+  // If we're parsing an ExprStmt and the last semicolon is missing and the
+  // incremental externsion is enabled and we're reaching the end, consider we
+  // want to do value printing. Note this is only enable in C++ mode
+  // since part of the implementation requires C++ language features.
+  //
+  // Note we shouldn't eat the token since the callback need it.
+  if (PP.isIncrementalProcessingEnabled() &&
+  Tok.is(tok::annot_repl_input_end) && Actions.getLangOpts().CPlusPlus)
+CurTok = 
+  else
+// Otherwise, eat the semicolon.
+ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+
+  StmtResult R = handleExprStmt(Expr, StmtCtx);
+  if (CurTok && !R.isInvalid())
+CurTok->setAnnotationValue(R.get());
+
+  return R;
 }
 
 /// ParseSEHTryBlockCommon
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2069,6 +2069,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   return;
 
 default:
@@ -5453,6 +5454,13 @@
 
   SmallVector DeclsInGroup;
   DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get()));
+
+  if (Tok.is(tok::annot_repl_input_end) &&
+  Tok.getAnnotationValue() != nullptr) {
+ConsumeAnnotationToken();
+cast(DeclsInGroup.back())->setValuePrinting();
+  }
+
   // Currently happens for things like  -fms-extensions and use `__if_exists`.
   for (Stmt *S : Stmts)
 DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S));
Index: clang/lib/Parse/ParseCXXInlineMethods.cpp
===
--- clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -836,6 +836,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of tokens.
   return false;
 
@@ -1242,6 +1243,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of tokens.
   return false;
 
Index: clang/lib/Lex/PPLexerChange.cpp
===
--- clang/lib/Lex/PPLexerChange.cpp
+++ clang/lib/Lex/PPLexerChange.cpp
@@ -535,13 +535,19 @@
   return LeavingSubmodule;
 }
   }
-
   // If this is the end of the main file, form an EOF token.
   assert(CurLexer && "Got EOF but no current lexer set!");
   const char *EndPos = getCurLexerEndPos();
   Result.startToken();
   CurLexer->BufferPtr = EndPos;
-  

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518292.
junaire added a comment.

.


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,93 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_TRUE(V1.hasValue());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_TRUE(V2.hasValue());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.hasValue());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_FALSE(V6.hasValue());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.hasValue());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.hasValue());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V8.isManuallyAlloc());
+
+  Value V9;
+  llvm::cantFail(Interp->ParseAndExecute("struct A { virtual int f(); };"));
+  llvm::cantFail(
+  

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Value.h:121
+static T cast(const Value ) {
+  if (V.isPointerOrObjectType())
+return (T)(uintptr_t)V.getAs();

aaron.ballman wrote:
> v.g.vassilev wrote:
> > aaron.ballman wrote:
> > > Do we have to worry about member function pointers where a single pointer 
> > > value may not be sufficient?
> > I am not sure if I understand your comment correctly. We only store objects 
> > and not function/member pointers (perhaps in some pathological way one 
> > could do that but I'd say it is not supported). Here we want to know if we 
> > stored it as a non-builtin type we need to make the pointer-like casts. My 
> > take is that for now we shouldn't worry about member function pointers.
> Given:
> ```
> struct Foo {
> struct Base {
>   virtual int bar();
> };
> 
> struct Foo : Base {
>   int bar() { return 12; }
> };
> 
> int (Foo::*bar_ptr)() = ::bar;
> ```
> The object `bar_ptr` requires two pointers of space to represent: 
> https://godbolt.org/z/o81sbjKM6, so I'm wondering whether `Value` can 
> represent `bar_ptr`
I added a test case for this.



Comment at: clang/include/clang/Interpreter/Value.h:143
+  /// Values referencing an object are treated as pointers to the object.
+  template  T castAs() const { return CastFwd::cast(*this); }
+

aaron.ballman wrote:
> v.g.vassilev wrote:
> > junaire wrote:
> > > aaron.ballman wrote:
> > > > This doesn't match the usual pattern used in Clang where the `get` 
> > > > variant returns `nullptr` and the `cast` variant asserts if the cast 
> > > > would be invalid. Should we go with a similar approach?
> > > These APIs are adopted in Cling and Cling will remove the old 
> > > implementation and use the upstream version of the value printing feature 
> > > at some point in the future. So @v.g.vassilev hope we can keep these APIs 
> > > close to Cling's variants as much as we can. I don't have a strong 
> > > opinion here, what's your take here? @v.g.vassilev 
> > I probably see the confusion. The `getAs` operation is only relevant for 
> > pointer types. For example we stored object of type `UserClass` as a 
> > pointer. For instance, I don't see how `getAs` can return a 
> > `nullptr`. We can probably inline the implementation of `getAs` for 
> > non-pointer types into `castAs` and leave `getAs` unimplemented relying 
> > only on the explicit specialization bellow for pointers.
> >  
> > The `castAs` operation means take a valid bit representation and transforms 
> > it into the requested one. I don't think it can or should be ever invalid. 
> > Here we are reshuffling bits.
> > 
> >  These changes are very subtle and if we decide to make changes we should 
> > open a pull request against the ROOT project to make sure we are not 
> > breaking some important case. The reference implementation is here: 
> > https://github.com/root-project/root/blob/master/interpreter/cling/include/cling/Interpreter/Value.h
> I think `castAs` can be invalid -- if you have the bits for a float and you 
> try to cast it as a pointer, that's not going to lead to good things, right?
> 
> My point is largely that the names `getAs` and `castAs` have meaning within 
> Clang already and this seems to assign slightly different meaning to them, 
> which might trip folks up. It might be worth considering renaming them to 
> something like `bitCast` and `pointerCast` (or something else, I'm not tied 
> to these names)?
We want to rename:
getAs --> as
castAs --> convertTo

Does these look good to you?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518290.
junaire added a comment.

.


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,89 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V8.isManuallyAlloc());
+
+  Value V9;
+  llvm::cantFail(Interp->ParseAndExecute("struct A { virtual int f(); };"));
+  llvm::cantFail(
+  Interp->ParseAndExecute("struct B : A { int f() { return 42; 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-04-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/test/Interpreter/pretty-print.cpp:107
+p2
+// CHECK-NEXT: (std::_MakeUniq::__single_object &) std::unique_ptr -> 
[[Addr:@0x.*]]
+

Hi @mizvekov, do you have a clue about why it doesn't print the correct type? 
So in `ValuePrinter.cpp:50` I dumped the type it shows:
```
AutoType 0x62d000533c00 'typename _MakeUniq::__single_object' sugar
`-ElaboratedType 0x62d000450500 'typename _MakeUniq::__single_object' sugar
  `-TypedefType 0x62d0004501e0 'std::_MakeUniq::__single_object' sugar
|-Typedef 0x62d000450160 '__single_object'
`-ElaboratedType 0x62d000450100 'unique_ptr' sugar
  `-TemplateSpecializationType 0x62d0004500b0 'unique_ptr' sugar 
unique_ptr
|-TemplateArgument type 'int':'int'
| `-SubstTemplateTypeParmType 0x62d00044fd50 'int' sugar typename depth 
0 index 0 _Tp
|   |-ClassTemplateSpecialization 0x62d00044fa08 '_MakeUniq'
|   `-BuiltinType 0x62119220 'int'
`-RecordType 0x62d000450080 'class std::unique_ptr'
  `-ClassTemplateSpecialization 0x62d00044ff70 'unique_ptr'
```

But in Cling it only has the RecordType. Do you think it's affected by your 
type resugaring patches?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-04-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518289.
junaire added a comment.

.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,148 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+int x = 42;
+x
+// CHECK-NEXT: (int) 42
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+
+struct S3 { int* p; S3() { p = new int(42); } ~S3() { delete p; } };
+S3{}
+// CHECK-NEXT: (S3) [[Addr:@0x.*]]
+S3 s3;
+s3
+// CHECK-NEXT: (S3 &) [[Addr:@0x.*]]
+
+struct S4 { ~S4() { printf("~S4()\n"); }};
+S4{}
+// CHECK-NEXT: (S4) [[Addr:@0x.*]]
+
+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
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+auto Lambda1 = []{};
+Lambda1
+// CHECK-NEXT: ((lambda) &) [[Addr:@0x.*]]
+[]{}
+// CHECK-NEXT: ((lambda at input_line_81:1:1)) [[Addr:@0x.*]]
+
+template struct F{ enum {RET=F::RET*n} ; };
+template<> struct F<0> { enum {RET = 1}; };
+F<7>::RET
+// CHECK-NEXT: (F<7>::(unnamed enum at input_line_84: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; }};
+::foo
+// CHECK-NEXT: (int (S5::*)()) Function [[Addr:@0x.*]]
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+auto p2 = std::make_unique(42);
+p2
+// CHECK-NEXT: (std::_MakeUniq::__single_object &) std::unique_ptr -> [[Addr:@0x.*]]
+
+#include 
+std::array a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array &) { 1, 2, 3 }
+
+#include 
+std::vector v = {7, 5, 16, 8};
+v
+// CHECK-NEXT: (std::vector &) { 7, 5, 16, 8 }
+
+#include 
+std::deque dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque &) { 7, 5, 16, 8 }
+
+#include 
+std::forward_list fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list &) { 3, 4, 5, 6 }
+
+#include 
+std::set z = {2,4,6,8};
+z
+// CHECK-NEXT: (std::set &) { 2, 4, 6, 8 }
+
+std::multiset e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset &) { 1, 2, 2, 3, 3, 4, 7 }
+
+#include 
+std::string std_str = "Hello, world!";
+std_str
+// CHECK-NEXT: (std::string &) "Hello, world!"
+
+struct MyType {};
+std::string PrintValueRuntime(const MyType*) { return "My pretty printer!"; }
+MyType{}
+// CHECK-NEXT: (MyType) My pretty printer!
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,530 @@
+#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/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+
+using namespace clang;
+
+static std::string PrintDeclType(const QualType , NamedDecl *D) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  if 

[PATCH] D148209: Add baseline tests for D148210

2023-04-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518288.
junaire added a comment.

.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148209

Files:
  llvm/test/Transforms/InstCombine/icmp.ll

Index: llvm/test/Transforms/InstCombine/icmp.ll
===
--- llvm/test/Transforms/InstCombine/icmp.ll
+++ llvm/test/Transforms/InstCombine/icmp.ll
@@ -4965,3 +4965,839 @@
   %cmp = icmp sgt i8 %b, 0
   ret i1 %cmp
 }
+
+define i1 @mul_mul_sge_zero(i8 %a, i8 %b) {
+; CHECK-LABEL: @mul_mul_sge_zero(
+; CHECK-NEXT:[[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42
+; CHECK-NEXT:[[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]]
+; CHECK-NEXT:[[CMP:%.*]] = icmp sgt i8 [[MUL2]], -1
+; CHECK-NEXT:ret i1 [[CMP]]
+;
+  %mul = mul nsw i8 %a, 42
+  %mul2 = mul nsw i8 %b, %mul
+  %cmp = icmp sge i8 %mul2, 0
+  ret i1 %cmp
+}
+
+define <2 x i1> @mul_mul_sge_zero_vec(<2 x i8> %a, <2 x i8> %b) {
+; CHECK-LABEL: @mul_mul_sge_zero_vec(
+; CHECK-NEXT:[[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]]
+; CHECK-NEXT:[[CMP:%.*]] = icmp sgt <2 x i8> [[MUL2]], 
+; CHECK-NEXT:ret <2 x i1> [[CMP]]
+;
+  %mul = mul nsw <2 x i8> %a, 
+  %mul2 = mul nsw <2 x i8> %b, %mul
+  %cmp = icmp sge <2 x i8> %mul2, 
+  ret <2 x i1> %cmp
+}
+
+define i1 @mul_mul_sge_one(i8 %a, i8 %b) {
+; CHECK-LABEL: @mul_mul_sge_one(
+; CHECK-NEXT:[[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42
+; CHECK-NEXT:[[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]]
+; CHECK-NEXT:[[CMP:%.*]] = icmp sgt i8 [[MUL2]], 0
+; CHECK-NEXT:ret i1 [[CMP]]
+;
+  %mul = mul nsw i8 %a, 42
+  %mul2 = mul nsw i8 %b, %mul
+  %cmp = icmp sge i8 %mul2, 1
+  ret i1 %cmp
+}
+
+define <2 x i1> @mul_mul_sge_one_vec(<2 x i8> %a, <2 x i8> %b) {
+; CHECK-LABEL: @mul_mul_sge_one_vec(
+; CHECK-NEXT:[[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]]
+; CHECK-NEXT:[[CMP:%.*]] = icmp sgt <2 x i8> [[MUL2]], zeroinitializer
+; CHECK-NEXT:ret <2 x i1> [[CMP]]
+;
+  %mul = mul nsw <2 x i8> %a, 
+  %mul2 = mul nsw <2 x i8> %b, %mul
+  %cmp = icmp sge <2 x i8> %mul2, 
+  ret <2 x i1> %cmp
+}
+
+define i1 @mul_mul_slt_zero(i8 %a, i8 %b) {
+; CHECK-LABEL: @mul_mul_slt_zero(
+; CHECK-NEXT:[[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42
+; CHECK-NEXT:[[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]]
+; CHECK-NEXT:[[CMP:%.*]] = icmp slt i8 [[MUL2]], 0
+; CHECK-NEXT:ret i1 [[CMP]]
+;
+  %mul = mul nsw i8 %a, 42
+  %mul2 = mul nsw i8 %b, %mul
+  %cmp = icmp slt i8 %mul2, 0
+  ret i1 %cmp
+}
+
+define <2 x i1> @mul_mul_slt_zero_vec(<2 x i8> %a, <2 x i8> %b) {
+; CHECK-LABEL: @mul_mul_slt_zero_vec(
+; CHECK-NEXT:[[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]]
+; CHECK-NEXT:[[CMP:%.*]] = icmp slt <2 x i8> [[MUL2]], zeroinitializer
+; CHECK-NEXT:ret <2 x i1> [[CMP]]
+;
+  %mul = mul nsw <2 x i8> %a, 
+  %mul2 = mul nsw <2 x i8> %b, %mul
+  %cmp = icmp slt <2 x i8> %mul2, 
+  ret <2 x i1> %cmp
+}
+
+define i1 @mul_mul_slt_one(i8 %a, i8 %b) {
+; CHECK-LABEL: @mul_mul_slt_one(
+; CHECK-NEXT:[[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42
+; CHECK-NEXT:[[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]]
+; CHECK-NEXT:[[CMP:%.*]] = icmp slt i8 [[MUL2]], 1
+; CHECK-NEXT:ret i1 [[CMP]]
+;
+  %mul = mul nsw i8 %a, 42
+  %mul2 = mul nsw i8 %b, %mul
+  %cmp = icmp slt i8 %mul2, 1
+  ret i1 %cmp
+}
+
+define <2 x i1> @mul_mul_slt_one_vec(<2 x i8> %a, <2 x i8> %b) {
+; CHECK-LABEL: @mul_mul_slt_one_vec(
+; CHECK-NEXT:[[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]]
+; CHECK-NEXT:[[CMP:%.*]] = icmp slt <2 x i8> [[MUL2]], 
+; CHECK-NEXT:ret <2 x i1> [[CMP]]
+;
+  %mul = mul nsw <2 x i8> %a, 
+  %mul2 = mul nsw <2 x i8> %b, %mul
+  %cmp = icmp slt <2 x i8> %mul2, 
+  ret <2 x i1> %cmp
+}
+
+define i1 @mul_mul_sle_zero(i8 %a, i8 %b) {
+; CHECK-LABEL: @mul_mul_sle_zero(
+; CHECK-NEXT:[[MUL:%.*]] = mul nsw i8 [[A:%.*]], 42
+; CHECK-NEXT:[[MUL2:%.*]] = mul nsw i8 [[MUL]], [[B:%.*]]
+; CHECK-NEXT:[[CMP:%.*]] = icmp slt i8 [[MUL2]], 1
+; CHECK-NEXT:ret i1 [[CMP]]
+;
+  %mul = mul nsw i8 %a, 42
+  %mul2 = mul nsw i8 %b, %mul
+  %cmp = icmp sle i8 %mul2, 0
+  ret i1 %cmp
+}
+
+define <2 x i1> @mul_mul_sle_zero_vec(<2 x i8> %a, <2 x i8> %b) {
+; CHECK-LABEL: @mul_mul_sle_zero_vec(
+; CHECK-NEXT:[[MUL:%.*]] = mul nsw <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[MUL2:%.*]] = mul nsw <2 x i8> [[MUL]], [[B:%.*]]
+; CHECK-NEXT:[[CMP:%.*]] = icmp slt <2 x i8> [[MUL2]], 
+; CHECK-NEXT:ret <2 x i1> [[CMP]]
+;
+  %mul = mul nsw <2 x i8> %a, 
+  %mul2 = mul nsw <2 x i8> %b, %mul
+  %cmp = icmp sle <2 x i8> %mul2, 
+  ret <2 x i1> %cmp
+}
+
+define i1 @mul_mul_sle_negone(i8 %a, i8 %b) {
+; CHECK-LABEL: 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-04-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518287.
junaire added a comment.

.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,148 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+int x = 42;
+x
+// CHECK-NEXT: (int) 42
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+
+struct S3 { int* p; S3() { p = new int(42); } ~S3() { delete p; } };
+S3{}
+// CHECK-NEXT: (S3) [[Addr:@0x.*]]
+S3 s3;
+s3
+// CHECK-NEXT: (S3 &) [[Addr:@0x.*]]
+
+struct S4 { ~S4() { printf("~S4()\n"); }};
+S4{}
+// CHECK-NEXT: (S4) [[Addr:@0x.*]]
+
+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
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+auto Lambda1 = []{};
+Lambda1
+// CHECK-NEXT: ((lambda) &) [[Addr:@0x.*]]
+[]{}
+// CHECK-NEXT: ((lambda at input_line_81:1:1)) [[Addr:@0x.*]]
+
+template struct F{ enum {RET=F::RET*n} ; };
+template<> struct F<0> { enum {RET = 1}; };
+F<7>::RET
+// CHECK-NEXT: (F<7>::(unnamed enum at input_line_84: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; }};
+::foo
+// CHECK-NEXT: (int (S5::*)()) Function [[Addr:@0x.*]]
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+auto p2 = std::make_unique(42);
+p2
+// CHECK-NEXT: (std::_MakeUniq::__single_object &) std::shared_ptr -> [[Addr:@0x.*]]
+
+#include 
+std::array a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array &) { 1, 2, 3 }
+
+#include 
+std::vector v = {7, 5, 16, 8};
+v
+// CHECK-NEXT: (std::vector &) { 7, 5, 16, 8 }
+
+#include 
+std::deque dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque &) { 7, 5, 16, 8 }
+
+#include 
+std::forward_list fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list &) { 3, 4, 5, 6 }
+
+#include 
+std::set z = {2,4,6,8};
+z
+// CHECK-NEXT: (std::set &) { 2, 4, 6, 8 }
+
+std::multiset e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset &) { 1, 2, 2, 3, 3, 4, 7 }
+
+#include 
+std::string std_str = "Hello, world!";
+std_str
+// CHECK-NEXT: (std::string &) "Hello, world!"
+
+struct MyType {};
+std::string PrintValueRuntime(const MyType*) { return "My pretty printer!"; }
+MyType{}
+// CHECK-NEXT: (MyType) My pretty printer!
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,530 @@
+#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/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+
+using namespace clang;
+
+static std::string PrintDeclType(const QualType , NamedDecl *D) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  if 

[PATCH] D148209: Add baseline tests for D148210

2023-04-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518286.
junaire added a comment.
Herald added subscribers: cfe-commits, mstorsjo.
Herald added a project: clang.

.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148209

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,148 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+int x = 42;
+x
+// CHECK-NEXT: (int) 42
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+
+struct S3 { int* p; S3() { p = new int(42); } ~S3() { delete p; } };
+S3{}
+// CHECK-NEXT: (S3) [[Addr:@0x.*]]
+S3 s3;
+s3
+// CHECK-NEXT: (S3 &) [[Addr:@0x.*]]
+
+struct S4 { ~S4() { printf("~S4()\n"); }};
+S4{}
+// CHECK-NEXT: (S4) [[Addr:@0x.*]]
+
+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
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+auto Lambda1 = []{};
+Lambda1
+// CHECK-NEXT: ((lambda) &) [[Addr:@0x.*]]
+[]{}
+// CHECK-NEXT: ((lambda at input_line_81:1:1)) [[Addr:@0x.*]]
+
+template struct F{ enum {RET=F::RET*n} ; };
+template<> struct F<0> { enum {RET = 1}; };
+F<7>::RET
+// CHECK-NEXT: (F<7>::(unnamed enum at input_line_84: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; }};
+::foo
+// CHECK-NEXT: (int (S5::*)()) Function [[Addr:@0x.*]]
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+auto p2 = std::make_unique(42);
+p2
+// CHECK-NEXT: (std::_MakeUniq::__single_object &) std::shared_ptr -> [[Addr:@0x.*]]
+
+#include 
+std::array a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array &) { 1, 2, 3 }
+
+#include 
+std::vector v = {7, 5, 16, 8};
+v
+// CHECK-NEXT: (std::vector &) { 7, 5, 16, 8 }
+
+#include 
+std::deque dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque &) { 7, 5, 16, 8 }
+
+#include 
+std::forward_list fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list &) { 3, 4, 5, 6 }
+
+#include 
+std::set z = {2,4,6,8};
+z
+// CHECK-NEXT: (std::set &) { 2, 4, 6, 8 }
+
+std::multiset e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset &) { 1, 2, 2, 3, 3, 4, 7 }
+
+#include 
+std::string std_str = "Hello, world!";
+std_str
+// CHECK-NEXT: (std::string &) "Hello, world!"
+
+struct MyType {};
+std::string PrintValueRuntime(const MyType*) { return "My pretty printer!"; }
+MyType{}
+// CHECK-NEXT: (MyType) My pretty printer!
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,530 @@
+#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/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+
+using namespace clang;
+
+static std::string PrintDeclType(const QualType , NamedDecl *D) {

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-30 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518285.
junaire marked 3 inline comments as done.
junaire added a comment.

Only enable __clang_Interpreter_SetValueCopyArr support in C++ mode.


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,88 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V8.isManuallyAlloc());
+
+  Value V9;
+  llvm::cantFail(Interp->ParseAndExecute("struct A { 

[PATCH] D146809: [clang-repl] Implement Value pretty printing

2023-04-29 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518266.
junaire added a comment.

.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,144 @@
+// 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
+extern "C" int printf(const char*,...);
+
+char c = 'a';
+c
+// CHECK: (char) 'a'
+
+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
+
+int x = 42;
+x
+// CHECK-NEXT: (int) 42
+
+
+// CHECK-NEXT: (int *) [[Addr:@0x.*]]
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S1{};
+S1 s1;
+s1
+// CHECK-NEXT: (S1 &) [[Addr:@0x.*]]
+
+S1{}
+// CHECK-NEXT: (S1) [[Addr:@0x.*]]
+
+struct S2 {int d;} E = {22};
+E
+// CHECK-NEXT: (struct S2 &) [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+
+struct S3 { int* p; S3() { p = new int(42); } ~S3() { delete p; } };
+S3{}
+// CHECK-NEXT: (S3) [[Addr:@0x.*]]
+S3 s3;
+s3
+// CHECK-NEXT: (S3 &) [[Addr:@0x.*]]
+
+struct S4 { ~S4() { printf("~S4()\n"); }};
+S4{}
+// CHECK-NEXT: (S4) [[Addr:@0x.*]]
+
+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
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+auto Lambda1 = []{};
+Lambda1
+// CHECK-NEXT: ((lambda) &) [[Addr:@0x.*]]
+[]{}
+// CHECK-NEXT: ((lambda at input_line_81:1:1)) [[Addr:@0x.*]]
+
+template struct F{ enum {RET=F::RET*n} ; };
+template<> struct F<0> { enum {RET = 1}; };
+F<7>::RET
+// CHECK-NEXT: (F<7>::(unnamed enum at input_line_84: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; }};
+::foo
+// CHECK-NEXT: (int (S5::*)()) Function [[Addr:@0x.*]]
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+#include 
+std::array a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array &) { 1, 2, 3 }
+
+#include 
+std::vector v = {7, 5, 16, 8};
+v
+// CHECK-NEXT: (std::vector &) { 7, 5, 16, 8 }
+
+#include 
+std::deque dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque &) { 7, 5, 16, 8 }
+
+#include 
+std::forward_list fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list &) { 3, 4, 5, 6 }
+
+#include 
+std::set z = {2,4,6,8};
+z
+// CHECK-NEXT: (std::set &) { 2, 4, 6, 8 }
+
+std::multiset e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset &) { 1, 2, 2, 3, 3, 4, 7 }
+
+#include 
+std::string std_str = "Hello, world!";
+std_str
+// CHECK-NEXT: (std::string &) "Hello, world!"
+
+struct MyType {};
+std::string PrintValueRuntime(const MyType*) { return "My pretty printer!"; }
+MyType{}
+// CHECK-NEXT: (MyType) My pretty printer!
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,530 @@
+#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/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+
+using namespace clang;
+
+static std::string PrintDeclType(const QualType , NamedDecl *D) {
+  std::string Str;
+  llvm::raw_string_ostream SS(Str);
+  if (QT.hasQualifiers())
+SS << QT.getQualifiers().getAsString() << " ";
+  SS << D->getQualifiedNameAsString();
+  return Str;
+}
+
+static 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-29 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518265.
junaire added a comment.

Add unittests for void & member pointers types


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,78 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+
+  Value V6;
+  llvm::cantFail(Interp->ParseAndExecute("void foo() {}"));
+  llvm::cantFail(Interp->ParseAndExecute("foo()", ));
+  EXPECT_TRUE(V6.isValid());
+  EXPECT_TRUE(V6.getType()->isVoidType());
+  EXPECT_EQ(V6.getKind(), Value::K_Void);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+
+  Value V7;
+  llvm::cantFail(Interp->ParseAndExecute("foo", ));
+  EXPECT_TRUE(V7.isValid());
+  EXPECT_TRUE(V7.getType()->isFunctionProtoType());
+  EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
+  EXPECT_FALSE(V7.isManuallyAlloc());
+
+  Value V8;
+  llvm::cantFail(Interp->ParseAndExecute("struct SS{ void f() {} };"));
+  llvm::cantFail(Interp->ParseAndExecute("::f", ));
+  EXPECT_TRUE(V8.isValid());
+  EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
+  EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V8.isManuallyAlloc());
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-29 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Interpreter.h:96
+
+  size_t getEffectivePTUSize() const;
+

aaron.ballman wrote:
> It looks like this can be private?
> 
> Also, just a note (not something you have to deal with in this review), the 
> local naming convention seems to have decided that if the function starts 
> with `get` then it's camel case and otherwise the name is pascal case.
Fixed.



Comment at: clang/include/clang/Interpreter/Value.h:83
+  Value() = default;
+  Value(void /*Interpreter*/ *In, void /*QualType*/ *Ty);
+  Value(const Value );

aaron.ballman wrote:
> v.g.vassilev wrote:
> > junaire wrote:
> > > aaron.ballman wrote:
> > > > Why do these take `void *` instead of the expected type?
> > > Yeah for the first parameter, we could just use `Interpreter*` but the 
> > > second one is an opaque type so I think we should keep it?
> > See my previous comments on performance. We cannot include anything bulky 
> > in the header file.
> I think I understand why the design is the way it is, but it still makes me 
> uneasy. The constructor takes a pointer to some bucket of bytes... no size 
> information, no type information, etc. Just "here's a random pointer". And 
> then later, we hope the user calls `setKind()` in a way that makes sense.
> 
> We need it to be fast, but we also need it to be correct -- the type system 
> is the best tool for helping with that.
Not really... The user doesn't need to call `setKind()` explicitly to construct 
a `Value`, the constructor will handle it automatically. See 
`ConvertQualTypeToKind` in `Value.cpp`. So if the pointer is just some garbage 
data, the constructor should fail before yielding out a valid instance.



Comment at: clang/lib/Interpreter/IncrementalParser.cpp:22
 #include "clang/FrontendTool/Utils.h"
+#include "clang/Interpreter/Interpreter.h"
 #include "clang/Parse/Parser.h"

aaron.ballman wrote:
> v.g.vassilev wrote:
> > This introduces a layering violation. Can we avoid it?
> Does it? This file is in `clang/lib/Interpreter` so including other things 
> from `clang/Interpreter` would not be a layering violation normally.
That's an old comment, already fixed and marked it as done :)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-29 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 518166.
junaire marked 4 inline comments as done.
junaire added a comment.

Partially address some comments


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Interpreter/Value.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/Value.cpp
@@ -0,0 +1,260 @@
+//===--- Interpreter.h - Incremental Compiation and 

[PATCH] D146809: [WIP][clang-repl] Implement Value pretty printing

2023-04-28 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 517836.
junaire added a comment.

Update


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,104 @@
+// 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
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S{};
+S s;
+s
+// CHECK-NEXT: (S &) [[Addr:@0x.*]]
+
+S{}
+// CHECK-NEXT: (S) [[Addr:@0x.*]]
+
+struct C {int d;} E = {22};
+E
+// CHECK-NEXT: [[Addr:@0x.*]]
+E.d
+// CHECK-NEXT: (int) 22
+
+struct SS { int* p; SS() { p = new int(42); } ~SS() { delete p; } };
+SS{}
+// CHECK-NEXT: (SS) [[Addr:@0x.*]]
+SS ss;
+ss
+// CHECK-NEXT: (SS &) [[Addr:@0x.*]]
+
+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
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+#include 
+std::array a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array &) { 1, 2, 3 }
+
+#include 
+std::vector v = {7, 5, 16, 8};
+v
+// CHECK-NEXT: (std::vector &) { 7, 5, 16, 8 }
+
+#include 
+std::deque dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque &) { 7, 5, 16, 8 }
+
+#include 
+std::forward_list fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list &) { 3, 4, 5, 6 }
+
+#include 
+std::set z = {2,4,6,8};
+z
+// CHECK-NEXT: (std::set &) { 2, 4, 6, 8 }
+
+std::multiset e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset &) { 1, 2, 2, 3, 3, 4, 7 }
+
+#include 
+std::string std_str = "Hello, world!";
+std_str
+// CHECK-NEXT: (std::string &) "Hello, world!"
+
+const char* c_str = "Goodbye, world!";
+c_str
+// CHECK-NEXT: (const char *) "Goodbye, world!"
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,497 @@
+#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/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+
+using namespace clang;
+
+static std::string PrintDeclType(const QualType , 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 , 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 >' rather than 'a>'.
+  Policy.SplitTemplateClosers = true;
+
+  struct LocalPrintingPolicyRAII {
+ASTContext 
+PrintingPolicy Policy;
+
+LocalPrintingPolicyRAII(ASTContext , PrintingPolicy )
+: 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(NonRefTy))
+SS << PrintDeclType(NonRefTy, TTy->getDecl());
+  else if (const auto *TRy = dyn_cast(NonRefTy))
+SS << 

[PATCH] D148997: [clang] Add a new annotation token: annot_repl_input_end

2023-04-28 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/lib/CodeGen/CodeGenModule.cpp:7219
 void CodeGenModule::moveLazyEmissionStates(CodeGenModule *NewBuilder) {
-  assert(DeferredDeclsToEmit.empty() &&
- "Should have emitted all decls deferred to emit.");
+  // FIXME: Re-enable the assertions once we fix regular codegen to not leave
+  // weak references behind.

I'll removed the change after https://reviews.llvm.org/D148435 landed.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148997

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D148997: [clang] Add a new annotation token: annot_repl_input_end

2023-04-28 Thread Jun Zhang via Phabricator via cfe-commits
junaire added a comment.

This patch is part of D141215 . I split it as 
some jit people requested. I don't know if there's a good way to test the 
patch, please leave a comment if you have an idea. Thanks.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148997

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-28 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 517829.
junaire added a comment.

fix windows buildbots


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,11 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+// JIT reports symbol not found on Windows without the visibility attribute.
+REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
+REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +282,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +320,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Interpreter/Value.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/Value.cpp
@@ -0,0 +1,260 @@
+//===--- Interpreter.h - Incremental Compiation and Execution---*- C++ -*-===//
+//
+// Part of the LLVM Project, 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-22 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 516081.
junaire added a comment.

Rebuild, please.


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +319,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Interpreter/Value.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/Value.cpp
@@ -0,0 +1,260 @@
+//===--- 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.
+// 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-22 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 516080.
junaire added a comment.

Break the IsSemiMissing/ repl_input_end parts out from the Value part


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/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +319,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Interpreter/Value.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/Value.cpp
@@ -0,0 +1,260 @@
+//===--- Interpreter.h - Incremental Compiation and Execution---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See 

[PATCH] D148997: [clang] Add a new annotation token: annot_repl_input_end

2023-04-22 Thread Jun Zhang via Phabricator via cfe-commits
junaire created this revision.
Herald added a project: All.
junaire requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This patch is the first part of the below RFC:
https://discourse.llvm.org/t/rfc-handle-execution-results-in-clang-repl/68493

It adds an annotation token which will replace the original EOF token
when we are in the incremental C++ mode. In addition, when we're
parsing an ExprStmt and there's a missing semicolon after the
expression, we set a marker in the annotation token and continue
parsing.

Eventually, we propogate this info in ParseTopLevelStmtDecl and are able
to mark this Decl as something we want to do value printing. Below is a
example:

clang-repl> int x = 42;
clang-repl> x
// `x` is a TopLevelStmtDecl and without a semicolon, we should set
// it's IsSemiMissing bit so we can do something interesting in
// ASTConsumer::HandleTopLevelDecl.

The idea about annotation toke is proposed by Richard Smith, thanks!

Signed-off-by: Jun Zhang 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D148997

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp

Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -320,6 +320,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Stop before we change submodules. They generally indicate a "good"
   // place to pick up parsing again (except in the special case where
   // we're trying to skip to EOF).
@@ -616,8 +617,8 @@
 
   // Skip over the EOF token, flagging end of previous input for incremental
   // processing
-  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof))
-ConsumeToken();
+  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::annot_repl_input_end))
+ConsumeAnnotationToken();
 
   Result = nullptr;
   switch (Tok.getKind()) {
@@ -697,6 +698,7 @@
 return false;
 
   case tok::eof:
+  case tok::annot_repl_input_end:
 // Check whether -fmax-tokens= was reached.
 if (PP.getMaxTokens() != 0 && PP.getTokenCount() > PP.getMaxTokens()) {
   PP.Diag(Tok.getLocation(), diag::warn_max_tokens_total)
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -543,9 +543,22 @@
 return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
   }
 
-  // Otherwise, eat the semicolon.
-  ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
-  return handleExprStmt(Expr, StmtCtx);
+  Token *CurTok = nullptr;
+  // If we're parsing an ExprStmt and the last semicolon is missing and the
+  // incremental externsion is enabled and we're reaching the end, consider we
+  // want to do value printing. Note we shouldn't eat the token since the
+  // callback need it.
+  if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::annot_repl_input_end))
+CurTok = 
+  else
+// Otherwise, eat the semicolon.
+ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
+
+  StmtResult R = handleExprStmt(Expr, StmtCtx);
+  if (!R.isInvalid() && CurTok)
+CurTok->setAnnotationValue(R.get());
+
+  return R;
 }
 
 /// ParseSEHTryBlockCommon
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -2069,6 +2069,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   return;
 
 default:
@@ -5453,6 +5454,13 @@
 
   SmallVector DeclsInGroup;
   DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get()));
+
+  if (Tok.is(tok::annot_repl_input_end) &&
+  Tok.getAnnotationValue() != nullptr) {
+ConsumeAnnotationToken();
+cast(DeclsInGroup.back())->setValuePrinting();
+  }
+
   // Currently happens for things like  -fms-extensions and use `__if_exists`.
   for (Stmt *S : Stmts)
 DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S));
Index: clang/lib/Parse/ParseCXXInlineMethods.cpp
===
--- clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -836,6 +836,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_repl_input_end:
   // Ran out of 

[PATCH] D148435: [clang-repl] Do not assert if we have weak references left.

2023-04-17 Thread Jun Zhang via Phabricator via cfe-commits
junaire accepted this revision.
junaire added a comment.
This revision is now accepted and ready to land.

This patch fixes issues that have not been found in the past. This unblocks 
D141215  and D146809 
. Since it's only relevant to the clang-repl, 
I believe this is safe to just land it. (I added these assertions in  
https://reviews.llvm.org/rGcd64a427efa0baaf1bb7ae624d4301908afc07f7 ) However, 
it will be nice if other reviewers, maybe @rjmccall could take a look at this 
as well.


Repository:
  rC Clang

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

https://reviews.llvm.org/D148435

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146809: [WIP][clang-repl] Implement Value pretty printing

2023-04-17 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 514160.
junaire added a comment.

Update


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,79 @@
+// 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
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S{};
+S s;
+s
+// CHECK-NEXT: (S &) [[Addr:@0x.*]]
+
+S{}
+// CHECK-NEXT: (S) [[Addr:@0x.*]]
+
+struct SS { int* p; SS() { p = new int(42); } ~SS() { delete p; } };
+SS{}
+// CHECK-NEXT: (SS) [[Addr:@0x.*]]
+SS ss;
+ss
+// CHECK-NEXT: (SS &) [[Addr:@0x.*]]
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+#include 
+std::array a{1, 2, 3};
+a
+// CHECK-NEXT: (std::array &) { 1, 2, 3 }
+
+#include 
+std::vector v = {7, 5, 16, 8};
+v
+// CHECK-NEXT: (std::vector &) { 7, 5, 16, 8 }
+
+#include 
+std::deque dq = {7, 5, 16, 8};
+dq
+// CHECK-NEXT: (std::deque &) { 7, 5, 16, 8 }
+
+#include 
+std::forward_list fl {3,4,5,6};
+fl
+// CHECK-NEXT: (std::forward_list &) { 3, 4, 5, 6 }
+
+#include 
+std::set z = {2,4,6,8};
+z
+// CHECK-NEXT: (std::set &) { 2, 4, 6, 8 }
+
+std::multiset e {3,2,1,2,4,7,3};
+e
+// CHECK-NEXT: (std::multiset &) { 1, 2, 2, 3, 3, 4, 7 }
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,501 @@
+#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/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+
+using namespace clang;
+
+static std::string PrintDeclType(const QualType , 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 , 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 >' rather than 'a>'.
+  Policy.SplitTemplateClosers = true;
+
+  struct LocalPrintingPolicyRAII {
+ASTContext 
+PrintingPolicy Policy;
+
+LocalPrintingPolicyRAII(ASTContext , PrintingPolicy )
+: 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(NonRefTy))
+SS << PrintDeclType(NonRefTy, TTy->getDecl());
+  else if (const auto *TRy = dyn_cast(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(NonRefTy)) {
+  // FIXME: TemplateSpecializationType & SubstTemplateTypeParmType checks
+  // are predominately to get STL containers to print nicer and might be
+  // better handled in GetFullyQualifiedName.
+  //
+ 

[PATCH] D146809: [WIP][clang-repl] Implement Value pretty printing

2023-04-16 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 513971.
junaire added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,51 @@
+// 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
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S{};
+S s;
+s
+// CHECK-NEXT: (S &) [[Addr:@0x.*]]
+
+S{}
+// CHECK-NEXT: (S) [[Addr:@0x.*]]
+
+struct SS { int* p; SS() { p = new int(42); } ~SS() { delete p; } };
+SS{}
+// CHECK-NEXT: (SS) [[Addr:@0x.*]]
+SS ss;
+ss
+// CHECK-NEXT: (SS &) [[Addr:@0x.*]]
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,506 @@
+#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/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+
+using namespace clang;
+
+namespace rep_runtime_internal {
+REPL_EXTERNAL_VISIBILITY
+extern const char *const kEmptyCollection = "{}";
+} // namespace rep_runtime_internal
+
+static std::string PrintDeclType(const QualType , 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 , 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 >' rather than 'a>'.
+  Policy.SplitTemplateClosers = true;
+
+  struct LocalPrintingPolicyRAII {
+ASTContext 
+PrintingPolicy Policy;
+
+LocalPrintingPolicyRAII(ASTContext , PrintingPolicy )
+: 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(NonRefTy))
+SS << PrintDeclType(NonRefTy, TTy->getDecl());
+  else if (const auto *TRy = dyn_cast(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(NonRefTy)) {
+  // FIXME: TemplateSpecializationType & SubstTemplateTypeParmType checks
+  // are predominately to get STL containers to print nicer and might be
+  // better handled in GetFullyQualifiedName.
+  //
+  // std::vector::iterator is a TemplateSpecializationType
+  // std::vector::value_type is a SubstTemplateTypeParmType
+  //
+  QualType SSDesugar = TDTy->getLocallyUnqualifiedSingleStepDesugaredType();
+  if (llvm::isa(SSDesugar))
+SS << GetFullTypeName(Ctx, Canon);
+  else if (llvm::isa(SSDesugar))
+SS << GetFullTypeName(Ctx, NonRefTy);
+  else
+SS << PrintDeclType(NonRefTy, TDTy->getDecl());

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire marked an inline comment as done.
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Value.h:98
+  QualType getType() const;
+  Interpreter () const;
+

sgraenitz wrote:
> Can we make this private and try not to introduce more dependencies on the 
> interpreter instance?
> 
> The inherent problem is that we will have to wire these through Orc RPC in 
> the future once we want to support out-of-process execution.
Ughh, I don't understand can you elaborate a bit? We can't make these accessors 
private since they are meaningful API?  it will be used intensively in 
`ValuePrinter.cpp` (the second patch), and the end users may want to use them 
as well.



Comment at: clang/include/clang/Interpreter/Value.h:143
+  /// Values referencing an object are treated as pointers to the object.
+  template  T castAs() const { return CastFwd::cast(*this); }
+

aaron.ballman wrote:
> This doesn't match the usual pattern used in Clang where the `get` variant 
> returns `nullptr` and the `cast` variant asserts if the cast would be 
> invalid. Should we go with a similar approach?
These APIs are adopted in Cling and Cling will remove the old implementation 
and use the upstream version of the value printing feature at some point in the 
future. So @v.g.vassilev hope we can keep these APIs close to Cling's variants 
as much as we can. I don't have a strong opinion here, what's your take here? 
@v.g.vassilev 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 513954.
junaire marked an inline comment as done.
junaire added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -315,4 +319,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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: 

[PATCH] D148434: [clang-repl] JITTargetAddress --> ExecutorAddr

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire marked an inline comment as done.
junaire added inline comments.



Comment at: clang/lib/Interpreter/IncrementalExecutor.cpp:88
 return Sym.takeError();
-  return Sym->getValue();
+  return llvm::orc::ExecutorAddr(Sym->getValue());
 }

sgraenitz wrote:
> I think `Sym` is a `Expected` already
good catch, thx!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148434

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D148434: [clang-repl] JITTargetAddress --> ExecutorAddr

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
junaire marked an inline comment as done.
Closed by commit rGfe1f34453d7e: [clang-repl] JITTargetAddress -- 
ExecutorAddr, NFC (authored by junaire).

Changed prior to commit:
  https://reviews.llvm.org/D148434?vs=513924=513953#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148434

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -225,7 +225,7 @@
 
   std::string MangledName = MangleName(FD);
   auto Addr = cantFail(Interp->getSymbolAddress(MangledName));
-  EXPECT_NE(0U, Addr);
+  EXPECT_NE(0U, Addr.getValue());
   GlobalDecl GD(FD);
   EXPECT_EQ(Addr, cantFail(Interp->getSymbolAddress(GD)));
 }
@@ -309,7 +309,8 @@
 
   std::string MangledName = MangleName(TmpltSpec);
   typedef int (*TemplateSpecFn)(void *);
-  auto fn = (TemplateSpecFn)cantFail(Interp->getSymbolAddress(MangledName));
+  auto fn =
+  cantFail(Interp->getSymbolAddress(MangledName)).toPtr();
   EXPECT_EQ(42, fn(NewA));
   free(NewA);
 }
Index: clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
===
--- clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -25,7 +25,6 @@
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/TargetSelect.h"
-#include "llvm-c/Error.h"
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
@@ -116,7 +115,8 @@
   llvm::cantFail(Interp->ParseAndExecute(ExceptionCode));
   testing::internal::CaptureStdout();
   auto ThrowException =
-  (int (*)())llvm::cantFail(Interp->getSymbolAddress("throw_exception"));
+  llvm::cantFail(Interp->getSymbolAddress("throw_exception"))
+  .toPtr();
   EXPECT_ANY_THROW(ThrowException());
   std::string CapturedStdOut = testing::internal::GetCapturedStdout();
   EXPECT_EQ(CapturedStdOut, "Caught: 'To be caught in JIT'\n");
Index: clang/lib/Interpreter/Interpreter.cpp
===
--- clang/lib/Interpreter/Interpreter.cpp
+++ clang/lib/Interpreter/Interpreter.cpp
@@ -246,7 +246,7 @@
   return llvm::Error::success();
 }
 
-llvm::Expected
+llvm::Expected
 Interpreter::getSymbolAddress(GlobalDecl GD) const {
   if (!IncrExecutor)
 return llvm::make_error("Operation failed. "
@@ -256,7 +256,7 @@
   return getSymbolAddress(MangledName);
 }
 
-llvm::Expected
+llvm::Expected
 Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
   if (!IncrExecutor)
 return llvm::make_error("Operation failed. "
@@ -266,7 +266,7 @@
   return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
 }
 
-llvm::Expected
+llvm::Expected
 Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
   if (!IncrExecutor)
 return llvm::make_error("Operation failed. "
Index: clang/lib/Interpreter/IncrementalExecutor.h
===
--- clang/lib/Interpreter/IncrementalExecutor.h
+++ clang/lib/Interpreter/IncrementalExecutor.h
@@ -16,6 +16,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
 
 #include 
 
@@ -51,7 +52,7 @@
   llvm::Error removeModule(PartialTranslationUnit );
   llvm::Error runCtors() const;
   llvm::Error cleanUp();
-  llvm::Expected
+  llvm::Expected
   getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const;
 
   llvm::orc::LLJIT () { return *Jit; }
Index: clang/lib/Interpreter/IncrementalExecutor.cpp
===
--- clang/lib/Interpreter/IncrementalExecutor.cpp
+++ clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -77,7 +77,7 @@
   return Jit->initialize(Jit->getMainJITDylib());
 }
 
-llvm::Expected
+llvm::Expected
 IncrementalExecutor::getSymbolAddress(llvm::StringRef Name,
   SymbolNameKind NameKind) const {
   auto Sym = (NameKind == LinkerName) ? Jit->lookupLinkerMangled(Name)
@@ -85,7 +85,7 @@
 
   if (!Sym)
 return Sym.takeError();
-  return Sym->getValue();
+  return Sym;
 }
 
 } // end namespace clang
Index: 

[PATCH] D146809: [WIP][clang-repl] Implement Value pretty printing

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 513927.
junaire added a comment.

Sync


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,51 @@
+// 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
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S{};
+S s;
+s
+// CHECK-NEXT: (S &) [[Addr:@0x.*]]
+
+S{}
+// CHECK-NEXT: (S) [[Addr:@0x.*]]
+
+struct SS { int* p; SS() { p = new int(42); } ~SS() { delete p; } };
+SS{}
+// CHECK-NEXT: (SS) [[Addr:@0x.*]]
+SS ss;
+ss
+// CHECK-NEXT: (SS &) [[Addr:@0x.*]]
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,507 @@
+#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/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+
+using namespace clang;
+
+namespace rep_runtime_internal {
+REPL_EXTERNAL_VISIBILITY
+extern const char *const kEmptyCollection = "{}";
+} // namespace rep_runtime_internal
+
+static std::string PrintDeclType(const QualType , 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 , 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 >' rather than 'a>'.
+  Policy.SplitTemplateClosers = true;
+
+  struct LocalPrintingPolicyRAII {
+ASTContext 
+PrintingPolicy Policy;
+
+LocalPrintingPolicyRAII(ASTContext , PrintingPolicy )
+: 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(NonRefTy))
+SS << PrintDeclType(NonRefTy, TTy->getDecl());
+  else if (const auto *TRy = dyn_cast(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(NonRefTy)) {
+  // FIXME: TemplateSpecializationType & SubstTemplateTypeParmType checks
+  // are predominately to get STL containers to print nicer and might be
+  // better handled in GetFullyQualifiedName.
+  //
+  // std::vector::iterator is a TemplateSpecializationType
+  // std::vector::value_type is a SubstTemplateTypeParmType
+  //
+  QualType SSDesugar = TDTy->getLocallyUnqualifiedSingleStepDesugaredType();
+  if (llvm::isa(SSDesugar))
+SS << GetFullTypeName(Ctx, Canon);
+  else if (llvm::isa(SSDesugar))
+SS << GetFullTypeName(Ctx, NonRefTy);
+  else
+SS << PrintDeclType(NonRefTy, TDTy->getDecl());
+ 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire marked an inline comment as done.
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Value.h:83
+  Value() = default;
+  Value(void /*Interpreter*/ *In, void /*QualType*/ *Ty);
+  Value(const Value );

aaron.ballman wrote:
> Why do these take `void *` instead of the expected type?
Yeah for the first parameter, we could just use `Interpreter*` but the second 
one is an opaque type so I think we should keep it?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 513926.
junaire marked an inline comment as done.
junaire added a comment.

Address more comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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

[PATCH] D148434: [clang-repl] JITTargetAddress --> ExecutorAddr

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 513924.
junaire added a comment.

Avoid unnecessary changes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148434

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -225,7 +225,7 @@
 
   std::string MangledName = MangleName(FD);
   auto Addr = cantFail(Interp->getSymbolAddress(MangledName));
-  EXPECT_NE(0U, Addr);
+  EXPECT_NE(0U, Addr.getValue());
   GlobalDecl GD(FD);
   EXPECT_EQ(Addr, cantFail(Interp->getSymbolAddress(GD)));
 }
@@ -309,7 +309,8 @@
 
   std::string MangledName = MangleName(TmpltSpec);
   typedef int (*TemplateSpecFn)(void *);
-  auto fn = (TemplateSpecFn)cantFail(Interp->getSymbolAddress(MangledName));
+  auto fn =
+  cantFail(Interp->getSymbolAddress(MangledName)).toPtr();
   EXPECT_EQ(42, fn(NewA));
   free(NewA);
 }
Index: clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
===
--- clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -25,7 +25,6 @@
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/TargetSelect.h"
-#include "llvm-c/Error.h"
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
@@ -116,7 +115,8 @@
   llvm::cantFail(Interp->ParseAndExecute(ExceptionCode));
   testing::internal::CaptureStdout();
   auto ThrowException =
-  (int (*)())llvm::cantFail(Interp->getSymbolAddress("throw_exception"));
+  llvm::cantFail(Interp->getSymbolAddress("throw_exception"))
+  .toPtr();
   EXPECT_ANY_THROW(ThrowException());
   std::string CapturedStdOut = testing::internal::GetCapturedStdout();
   EXPECT_EQ(CapturedStdOut, "Caught: 'To be caught in JIT'\n");
Index: clang/lib/Interpreter/Interpreter.cpp
===
--- clang/lib/Interpreter/Interpreter.cpp
+++ clang/lib/Interpreter/Interpreter.cpp
@@ -246,7 +246,7 @@
   return llvm::Error::success();
 }
 
-llvm::Expected
+llvm::Expected
 Interpreter::getSymbolAddress(GlobalDecl GD) const {
   if (!IncrExecutor)
 return llvm::make_error("Operation failed. "
@@ -256,7 +256,7 @@
   return getSymbolAddress(MangledName);
 }
 
-llvm::Expected
+llvm::Expected
 Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
   if (!IncrExecutor)
 return llvm::make_error("Operation failed. "
@@ -266,7 +266,7 @@
   return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
 }
 
-llvm::Expected
+llvm::Expected
 Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
   if (!IncrExecutor)
 return llvm::make_error("Operation failed. "
Index: clang/lib/Interpreter/IncrementalExecutor.h
===
--- clang/lib/Interpreter/IncrementalExecutor.h
+++ clang/lib/Interpreter/IncrementalExecutor.h
@@ -16,6 +16,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
 
 #include 
 
@@ -51,7 +52,7 @@
   llvm::Error removeModule(PartialTranslationUnit );
   llvm::Error runCtors() const;
   llvm::Error cleanUp();
-  llvm::Expected
+  llvm::Expected
   getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const;
 
   llvm::orc::LLJIT () { return *Jit; }
Index: clang/lib/Interpreter/IncrementalExecutor.cpp
===
--- clang/lib/Interpreter/IncrementalExecutor.cpp
+++ clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -77,7 +77,7 @@
   return Jit->initialize(Jit->getMainJITDylib());
 }
 
-llvm::Expected
+llvm::Expected
 IncrementalExecutor::getSymbolAddress(llvm::StringRef Name,
   SymbolNameKind NameKind) const {
   auto Sym = (NameKind == LinkerName) ? Jit->lookupLinkerMangled(Name)
@@ -85,7 +85,7 @@
 
   if (!Sym)
 return Sym.takeError();
-  return Sym->getValue();
+  return llvm::orc::ExecutorAddr(Sym->getValue());
 }
 
 } // end namespace clang
Index: clang/include/clang/Interpreter/Interpreter.h
===
--- clang/include/clang/Interpreter/Interpreter.h
+++ clang/include/clang/Interpreter/Interpreter.h
@@ -19,6 +19,7 @@
 #include 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire marked 4 inline comments as done.
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Interpreter.h:83
   /// mangled name.
   llvm::Expected getSymbolAddress(GlobalDecl GD) const;
 

sgraenitz wrote:
> Most of the Orc and JITLink moved away from `JITTargetAddress` already and 
> uses `ExecutorAddr` nowadays. I think we should use `ExecutorAddr` from the 
> beginning in this patch.
Thanks, I've created https://reviews.llvm.org/D148434


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D148434: [clang-repl] JITTargetAddress --> ExecutorAddr

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire created this revision.
Herald added a project: All.
junaire requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Signed-off-by: Jun Zhang 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D148434

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -225,7 +225,7 @@
 
   std::string MangledName = MangleName(FD);
   auto Addr = cantFail(Interp->getSymbolAddress(MangledName));
-  EXPECT_NE(0U, Addr);
+  EXPECT_NE(0U, Addr.getValue());
   GlobalDecl GD(FD);
   EXPECT_EQ(Addr, cantFail(Interp->getSymbolAddress(GD)));
 }
@@ -309,7 +309,8 @@
 
   std::string MangledName = MangleName(TmpltSpec);
   typedef int (*TemplateSpecFn)(void *);
-  auto fn = (TemplateSpecFn)cantFail(Interp->getSymbolAddress(MangledName));
+  auto fn =
+  cantFail(Interp->getSymbolAddress(MangledName)).toPtr();
   EXPECT_EQ(42, fn(NewA));
   free(NewA);
 }
Index: clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
===
--- clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
+++ clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp
@@ -21,11 +21,11 @@
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 
+#include "llvm-c/Error.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/TargetSelect.h"
-#include "llvm-c/Error.h"
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
@@ -116,7 +116,8 @@
   llvm::cantFail(Interp->ParseAndExecute(ExceptionCode));
   testing::internal::CaptureStdout();
   auto ThrowException =
-  (int (*)())llvm::cantFail(Interp->getSymbolAddress("throw_exception"));
+  llvm::cantFail(Interp->getSymbolAddress("throw_exception"))
+  .toPtr();
   EXPECT_ANY_THROW(ThrowException());
   std::string CapturedStdOut = testing::internal::GetCapturedStdout();
   EXPECT_EQ(CapturedStdOut, "Caught: 'To be caught in JIT'\n");
Index: clang/lib/Interpreter/Interpreter.cpp
===
--- clang/lib/Interpreter/Interpreter.cpp
+++ clang/lib/Interpreter/Interpreter.cpp
@@ -246,7 +246,7 @@
   return llvm::Error::success();
 }
 
-llvm::Expected
+llvm::Expected
 Interpreter::getSymbolAddress(GlobalDecl GD) const {
   if (!IncrExecutor)
 return llvm::make_error("Operation failed. "
@@ -256,7 +256,7 @@
   return getSymbolAddress(MangledName);
 }
 
-llvm::Expected
+llvm::Expected
 Interpreter::getSymbolAddress(llvm::StringRef IRName) const {
   if (!IncrExecutor)
 return llvm::make_error("Operation failed. "
@@ -266,7 +266,7 @@
   return IncrExecutor->getSymbolAddress(IRName, IncrementalExecutor::IRName);
 }
 
-llvm::Expected
+llvm::Expected
 Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
   if (!IncrExecutor)
 return llvm::make_error("Operation failed. "
Index: clang/lib/Interpreter/IncrementalExecutor.h
===
--- clang/lib/Interpreter/IncrementalExecutor.h
+++ clang/lib/Interpreter/IncrementalExecutor.h
@@ -51,7 +51,7 @@
   llvm::Error removeModule(PartialTranslationUnit );
   llvm::Error runCtors() const;
   llvm::Error cleanUp();
-  llvm::Expected
+  llvm::Expected
   getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const;
 
   llvm::orc::LLJIT () { return *Jit; }
Index: clang/lib/Interpreter/IncrementalExecutor.cpp
===
--- clang/lib/Interpreter/IncrementalExecutor.cpp
+++ clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -21,6 +21,7 @@
 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/ManagedStatic.h"
@@ -77,7 +78,7 @@
   return Jit->initialize(Jit->getMainJITDylib());
 }
 
-llvm::Expected
+llvm::Expected
 IncrementalExecutor::getSymbolAddress(llvm::StringRef Name,
   SymbolNameKind NameKind) const {
   auto Sym = (NameKind == LinkerName) ? Jit->lookupLinkerMangled(Name)
@@ -85,7 +86,7 @@
 
   if (!Sym)
 return Sym.takeError();
-  return Sym->getValue();
+ 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire marked 16 inline comments as done.
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Interpreter.h:72
+  llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr);
+  llvm::Expected CompileDtorCall(CXXRecordDecl *CXXRD);
 

aaron.ballman wrote:
> Hopefully this function isn't intending to mutate the passed object?
Unfortunately `Sema::LookupDestructor` ask for a non-const pointer... 
(https://github.com/llvm/llvm-project/blob/26e164fada3721b0939e6b7c2dfe1793d95229bb/clang/lib/Sema/SemaLookup.cpp#L3625)



Comment at: clang/include/clang/Interpreter/Interpreter.h:102
+
+  Expr *SynthesizeExpr(clang::Expr *E);
+

aaron.ballman wrote:
> Any chance we can make this const correct as well? (I'll stop asking in this 
> review -- can you take a pass through it to add const correctness where it 
> isn't obnoxiously viral to do so?)
FindRuntimeInterface mutates ValuePrintingInfo vector so it can't be const 
afaict.



Comment at: clang/include/clang/Interpreter/Value.h:17
+
+#include 
+

aaron.ballman wrote:
> Unused include can be removed.
uintptr_t comes from this header so it's not unused.



Comment at: clang/include/clang/Interpreter/Value.h:77
+
+K_Void,
+K_PtrOrObj,

aaron.ballman wrote:
> Fixing indentation
It's already formatted by clang-format and if I change this arc doesn't even 
allow me to upload the diff. I believe it's a bug in clang-format and I have 
filed https://github.com/llvm/llvm-project/issues/60535 So I'd like to fix this 
when I commit this :)



Comment at: clang/lib/Interpreter/Interpreter.cpp:534
+}
+  llvm_unreachable("Unknown runtime interface kind");
+}

sgraenitz wrote:
> Is this a leftover from an old `default` label?
there's no default label since we handle all the cases here. But indeed it 
looks a bit ugly and I removed it.



Comment at: clang/lib/Interpreter/Value.cpp:91
+  static constexpr unsigned char Canary[8] = {0x4c, 0x37, 0xad, 0x8f,
+  0x2d, 0x23, 0x95, 0x91};
+};

sgraenitz wrote:
> Can we add a comment with an explanation of the magic numbers please?
I'm uncertain if these numbers actually have specific meanings, I just copied 
them from Cling directly.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-15 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 513918.
junaire added a comment.

Address some comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Parse/Parser.cpp

[PATCH] D146809: [WIP][clang-repl] Implement Value pretty printing

2023-04-12 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 513024.
junaire added a comment.

Update


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,51 @@
+// 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
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S{};
+S s;
+s
+// CHECK-NEXT: (S &) [[Addr:@0x.*]]
+
+S{}
+// CHECK-NEXT: (S) [[Addr:@0x.*]]
+
+struct SS { int* p; SS() { p = new int(42); } ~SS() { delete p; } };
+SS{}
+// CHECK-NEXT: (SS) [[Addr:@0x.*]]
+SS ss;
+ss
+// CHECK-NEXT: (SS &) [[Addr:@0x.*]]
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,507 @@
+#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/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+
+using namespace clang;
+
+namespace rep_runtime_internal {
+REPL_EXTERNAL_VISIBILITY
+extern const char *const kEmptyCollection = "{}";
+} // namespace rep_runtime_internal
+
+static std::string PrintDeclType(const QualType , 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 , 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 >' rather than 'a>'.
+  Policy.SplitTemplateClosers = true;
+
+  struct LocalPrintingPolicyRAII {
+ASTContext 
+PrintingPolicy Policy;
+
+LocalPrintingPolicyRAII(ASTContext , PrintingPolicy )
+: 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(NonRefTy))
+SS << PrintDeclType(NonRefTy, TTy->getDecl());
+  else if (const auto *TRy = dyn_cast(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(NonRefTy)) {
+  // FIXME: TemplateSpecializationType & SubstTemplateTypeParmType checks
+  // are predominately to get STL containers to print nicer and might be
+  // better handled in GetFullyQualifiedName.
+  //
+  // std::vector::iterator is a TemplateSpecializationType
+  // std::vector::value_type is a SubstTemplateTypeParmType
+  //
+  QualType SSDesugar = TDTy->getLocallyUnqualifiedSingleStepDesugaredType();
+  if (llvm::isa(SSDesugar))
+SS << GetFullTypeName(Ctx, Canon);
+  else if (llvm::isa(SSDesugar))
+SS << GetFullTypeName(Ctx, NonRefTy);
+  else
+SS << PrintDeclType(NonRefTy, TDTy->getDecl());

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-12 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 512869.
junaire added a comment.

fix ci


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Parse/Parser.cpp

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-12 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 512837.
junaire added a comment.

dont include  if we don't have it


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Parse/Parser.cpp

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-12 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 512801.
junaire added a comment.

use unsigned long instead of std::size_t when including the runtimes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-10 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 512075.
junaire added a comment.

Use IncrementalParser::GetMangledName instead


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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: 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-10 Thread Jun Zhang via Phabricator via cfe-commits
junaire marked 6 inline comments as done.
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Interpreter.h:67
   create(std::unique_ptr CI);
+  ASTContext () const;
   const CompilerInstance *getCompilerInstance() const;

v.g.vassilev wrote:
> We should not need this. `CompileDtorCall` can probably do 
> `RD->getASTContext()` instead.
This is a really convenient helper, I'd proposed to keep it.



Comment at: clang/lib/Interpreter/Interpreter.cpp:350
   std::list  = IncrParser->getPTUs();
-  if (N > PTUs.size())
+  if (N + InitPTUSize > PTUs.size())
 return llvm::make_error("Operation failed. "

junaire wrote:
> v.g.vassilev wrote:
> > junaire wrote:
> > > v.g.vassilev wrote:
> > > > v.g.vassilev wrote:
> > > > > I'd propose `IncrParser->getPTUs()` to return the list starting from 
> > > > > `InitPTUSize`. That should solve the issue you see.
> > > > Ping.
> > > I'm uncertain about how to do this. Can you elaborate?
> > The `std::list PTUs;` in `IncrementalParser.h` 
> > stores the all PTUs that we saw, including the Interpreter builtins which 
> > contain declarations required by the Interpreter to run. I'd propose  to 
> > make `PTUs` of type `std::vector` and `getPTUs()` to return an `ArrayRef` 
> > starting from `PTUs.begin() + N` where `N` is the number of builtins that 
> > we must not undo.
> OK, return ArrayRef sounds good to me.
ArrayRef doesn't fit our needs, using getEffectivePTUSize instead.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-09 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 512073.
junaire added a comment.

fix some nits


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Parse/Parser.cpp

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-09 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 512072.
junaire added a comment.

Address some comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Parse/Parser.cpp

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-09 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Interpreter.h:97
+
+  enum InterfaceKind { NoAlloc, WithAlloc, CopyArray };
+

v.g.vassilev wrote:
> junaire wrote:
> > v.g.vassilev wrote:
> > > This can probably go in the RuntimeInterfaceBuilder class.
> > We need it. See:
> > 
> > ```
> > class RuntimeInterfaceBuilder
> > : public TypeVisitor > Interpreter::InterfaceKind> {
> >...
> > }
> > ```
> Can't this be an enum which is file local?
You can't put this enum inside RuntimeInterfaceBuilder because its declaration 
needs it. If you do so, then the above line will report an error since you use 
the enum before defined it.



Comment at: clang/lib/Interpreter/Interpreter.cpp:350
   std::list  = IncrParser->getPTUs();
-  if (N > PTUs.size())
+  if (N + InitPTUSize > PTUs.size())
 return llvm::make_error("Operation failed. "

v.g.vassilev wrote:
> junaire wrote:
> > v.g.vassilev wrote:
> > > v.g.vassilev wrote:
> > > > I'd propose `IncrParser->getPTUs()` to return the list starting from 
> > > > `InitPTUSize`. That should solve the issue you see.
> > > Ping.
> > I'm uncertain about how to do this. Can you elaborate?
> The `std::list PTUs;` in `IncrementalParser.h` stores 
> the all PTUs that we saw, including the Interpreter builtins which contain 
> declarations required by the Interpreter to run. I'd propose  to make `PTUs` 
> of type `std::vector` and `getPTUs()` to return an `ArrayRef` starting from 
> `PTUs.begin() + N` where `N` is the number of builtins that we must not undo.
OK, return ArrayRef sounds good to me.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-09 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 511999.
junaire added a comment.

Address some comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Parse/Parser.cpp

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-09 Thread Jun Zhang via Phabricator via cfe-commits
junaire added inline comments.



Comment at: clang/include/clang/Interpreter/Interpreter.h:97
+
+  enum InterfaceKind { NoAlloc, WithAlloc, CopyArray };
+

v.g.vassilev wrote:
> This can probably go in the RuntimeInterfaceBuilder class.
We need it. See:

```
class RuntimeInterfaceBuilder
: public TypeVisitor {
   ...
}
```



Comment at: clang/lib/Interpreter/Interpreter.cpp:350
   std::list  = IncrParser->getPTUs();
-  if (N > PTUs.size())
+  if (N + InitPTUSize > PTUs.size())
 return llvm::make_error("Operation failed. "

v.g.vassilev wrote:
> v.g.vassilev wrote:
> > I'd propose `IncrParser->getPTUs()` to return the list starting from 
> > `InitPTUSize`. That should solve the issue you see.
> Ping.
I'm uncertain about how to do this. Can you elaborate?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-09 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 511984.
junaire added a comment.

Refactor how we compile a destructor


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,55 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute(
+  "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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: 

[PATCH] D146809: [WIP][clang-repl] Implement Value pretty printing

2023-04-08 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 511871.
junaire added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146809

Files:
  clang/include/clang/Interpreter/Interpreter.h
  clang/lib/Headers/CMakeLists.txt
  clang/lib/Headers/__clang_interpreter_runtime_printvalue.h
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Interpreter/ValuePrinter.cpp
  clang/test/Interpreter/pretty-print.cpp

Index: clang/test/Interpreter/pretty-print.cpp
===
--- /dev/null
+++ clang/test/Interpreter/pretty-print.cpp
@@ -0,0 +1,51 @@
+// 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
+
+x - 2
+// CHECK-NEXT: (int) 40
+
+float f = 4.2f;
+f
+// CHECK-NEXT: (float) 4.2f
+
+double d = 4.21;
+d
+// CHECK-NEXT: (double) 4.210
+
+struct S{};
+S s;
+s
+// CHECK-NEXT: (S &) [[Addr:@0x.*]]
+
+S{}
+// CHECK-NEXT: (S) [[Addr:@0x.*]]
+
+struct SS { int* p; SS() { p = new int(42); } ~SS() { delete p; } };
+SS{}
+// CHECK-NEXT: (SS) [[Addr:@0x.*]]
+SS ss;
+ss
+// CHECK-NEXT: (SS &) [[Addr:@0x.*]]
+
+int arr[3] = {1,2,3};
+arr
+// CHECK-NEXT: (int[3]) { 1, 2, 3 }
+
+#include 
+
+auto p1 = std::make_shared(42);
+p1
+// CHECK-NEXT: (shared_ptr &) std::shared_ptr -> [[Addr:@0x.*]]
+
+%quit
+
Index: clang/lib/Interpreter/ValuePrinter.cpp
===
--- /dev/null
+++ clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,507 @@
+#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/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+
+using namespace clang;
+
+namespace rep_runtime_internal {
+REPL_EXTERNAL_VISIBILITY
+extern const char *const kEmptyCollection = "{}";
+} // namespace rep_runtime_internal
+
+static std::string PrintDeclType(const QualType , 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 , 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 >' rather than 'a>'.
+  Policy.SplitTemplateClosers = true;
+
+  struct LocalPrintingPolicyRAII {
+ASTContext 
+PrintingPolicy Policy;
+
+LocalPrintingPolicyRAII(ASTContext , PrintingPolicy )
+: 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(NonRefTy))
+SS << PrintDeclType(NonRefTy, TTy->getDecl());
+  else if (const auto *TRy = dyn_cast(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(NonRefTy)) {
+  // FIXME: TemplateSpecializationType & SubstTemplateTypeParmType checks
+  // are predominately to get STL containers to print nicer and might be
+  // better handled in GetFullyQualifiedName.
+  //
+  // std::vector::iterator is a TemplateSpecializationType
+  // std::vector::value_type is a SubstTemplateTypeParmType
+  //
+  QualType SSDesugar = TDTy->getLocallyUnqualifiedSingleStepDesugaredType();
+  if (llvm::isa(SSDesugar))
+SS << GetFullTypeName(Ctx, Canon);
+  else if (llvm::isa(SSDesugar))
+SS << GetFullTypeName(Ctx, NonRefTy);
+  else
+SS << PrintDeclType(NonRefTy, TDTy->getDecl());

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-08 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 511870.
junaire added a comment.

Remove some unnecessary code.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,54 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute("struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Parse/Parser.cpp

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-08 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 511867.
junaire added a comment.

Address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,54 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute("struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Parse/Parser.cpp

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-08 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 511862.
junaire added a comment.

Clean up the patch


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalASTConsumer.cpp
  clang/lib/Interpreter/IncrementalASTConsumer.h
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,54 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_TRUE(V1.isValid());
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+  EXPECT_EQ(V1.getKind(), Value::K_Int);
+  EXPECT_FALSE(V1.isManuallyAlloc());
+  EXPECT_FALSE(V1.isPointerOrObjectType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_TRUE(V2.isValid());
+  EXPECT_EQ(V2.getDouble(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.getKind(), Value::K_Double);
+  EXPECT_FALSE(V2.isManuallyAlloc());
+  EXPECT_FALSE(V2.isPointerOrObjectType());
+
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute("struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
+  llvm::cantFail(Interp->ParseAndExecute("S{}", ));
+  EXPECT_TRUE(V3.isValid());
+  EXPECT_TRUE(V3.getType()->isRecordType());
+  EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
+  EXPECT_TRUE(V3.isManuallyAlloc());
+  EXPECT_TRUE(V3.isPointerOrObjectType());
+
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 42);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  Value V5;
+  // Change the global from the compiled code.
+  setGlobal(43);
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V5.getInt(), 43);
+  EXPECT_TRUE(V5.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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
   

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-08 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 511857.
junaire added a comment.

Update...


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalASTConsumer.cpp
  clang/lib/Interpreter/IncrementalASTConsumer.h
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,38 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_EQ(V2.getAs(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.castAs(), 3);
+
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V3.getInt(), 42);
+  EXPECT_TRUE(V3.getType()->isIntegerType());
+
+  // Change the global from the compiled code.
+  setGlobal(43);
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 43);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -320,6 +320,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_input_end:
   // Stop before we change submodules. They generally indicate a "good"
   // place to pick up parsing again (except in the special case where
   // we're trying to skip to EOF).
@@ -616,8 +617,8 @@
 
   // Skip 

[PATCH] D141215: [clang-repl] Introduce Value to capture expression results

2023-04-05 Thread Jun Zhang via Phabricator via cfe-commits
junaire updated this revision to Diff 511090.
junaire added a comment.

Remove old code


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141215

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Interpreter/Interpreter.h
  clang/include/clang/Interpreter/Value.h
  clang/include/clang/Parse/Parser.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/lib/Interpreter/CMakeLists.txt
  clang/lib/Interpreter/IncrementalASTConsumer.cpp
  clang/lib/Interpreter/IncrementalASTConsumer.h
  clang/lib/Interpreter/IncrementalExecutor.cpp
  clang/lib/Interpreter/IncrementalExecutor.h
  clang/lib/Interpreter/IncrementalParser.cpp
  clang/lib/Interpreter/IncrementalParser.h
  clang/lib/Interpreter/Interpreter.cpp
  clang/lib/Interpreter/InterpreterUtils.cpp
  clang/lib/Interpreter/InterpreterUtils.h
  clang/lib/Interpreter/Value.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Parse/ParseCXXInlineMethods.cpp
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/Parser.cpp
  clang/tools/clang-repl/CMakeLists.txt
  clang/unittests/Interpreter/CMakeLists.txt
  clang/unittests/Interpreter/InterpreterTest.cpp

Index: clang/unittests/Interpreter/InterpreterTest.cpp
===
--- clang/unittests/Interpreter/InterpreterTest.cpp
+++ clang/unittests/Interpreter/InterpreterTest.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Mangle.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Interpreter/Value.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Sema.h"
 
@@ -33,6 +34,10 @@
 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
 #endif
 
+int Global = 42;
+int getGlobal() { return Global; }
+void setGlobal(int val) { Global = val; }
+
 namespace {
 using Args = std::vector;
 static std::unique_ptr
@@ -276,8 +281,7 @@
   std::vector Args = {"-fno-delayed-template-parsing"};
   std::unique_ptr Interp = createInterpreter(Args);
 
-  llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
-   "extern \"C\" int printf(const char*,...);"
+  llvm::cantFail(Interp->Parse("extern \"C\" int printf(const char*,...);"
"class A {};"
"struct B {"
"  template"
@@ -314,4 +318,38 @@
   free(NewA);
 }
 
+TEST(InterpreterTest, Value) {
+  std::unique_ptr Interp = createInterpreter();
+
+  Value V1;
+  llvm::cantFail(Interp->ParseAndExecute("int x = 42;"));
+  llvm::cantFail(Interp->ParseAndExecute("x", ));
+  EXPECT_EQ(V1.getInt(), 42);
+  EXPECT_TRUE(V1.getType()->isIntegerType());
+
+  Value V2;
+  llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;"));
+  llvm::cantFail(Interp->ParseAndExecute("y", ));
+  EXPECT_EQ(V2.getAs(), 3.14);
+  EXPECT_TRUE(V2.getType()->isFloatingType());
+  EXPECT_EQ(V2.castAs(), 3);
+
+  llvm::cantFail(Interp->ParseAndExecute("int getGlobal();"));
+  llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);"));
+  Value V3;
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V3.getInt(), 42);
+  EXPECT_TRUE(V3.getType()->isIntegerType());
+
+  // Change the global from the compiled code.
+  setGlobal(43);
+  Value V4;
+  llvm::cantFail(Interp->ParseAndExecute("getGlobal()", ));
+  EXPECT_EQ(V4.getInt(), 43);
+  EXPECT_TRUE(V4.getType()->isIntegerType());
+
+  // Change the global from the interpreted code.
+  llvm::cantFail(Interp->ParseAndExecute("setGlobal(44);"));
+  EXPECT_EQ(getGlobal(), 44);
+}
 } // end anonymous namespace
Index: clang/unittests/Interpreter/CMakeLists.txt
===
--- clang/unittests/Interpreter/CMakeLists.txt
+++ clang/unittests/Interpreter/CMakeLists.txt
@@ -22,3 +22,5 @@
 if(NOT WIN32)
   add_subdirectory(ExceptionTests)
 endif()
+
+export_executable_symbols(ClangReplInterpreterTests)
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/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -320,6 +320,7 @@
 case tok::annot_module_begin:
 case tok::annot_module_end:
 case tok::annot_module_include:
+case tok::annot_input_end:
   // Stop before we change submodules. They generally indicate a "good"
   // place to pick up parsing again (except in the special case where
   // we're trying to skip to EOF).
@@ -616,8 +617,8 @@
 
   // 

  1   2   3   4   >