aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Interpreter/InterpreterTest.cpp
diff options
context:
space:
mode:
authorJun Zhang <jun@junz.org>2022-06-19 10:39:03 +0800
committerJun Zhang <jun@junz.org>2022-06-26 18:32:18 +0800
commitdea5a9cc929048be261a4c030407e4d7e1e70fec (patch)
tree1f3d283a91bf82b48deddec6b36bfa9ddbae7259 /clang/unittests/Interpreter/InterpreterTest.cpp
parent9de8b05bfe0de2915d2443d06159396c5f9d389f (diff)
downloadllvm-dea5a9cc929048be261a4c030407e4d7e1e70fec.zip
llvm-dea5a9cc929048be261a4c030407e4d7e1e70fec.tar.gz
llvm-dea5a9cc929048be261a4c030407e4d7e1e70fec.tar.bz2
[clang-repl] Implement code undo.
In interactive C++ it is convenient to roll back to a previous state of the compiler. For example: clang-repl> int x = 42; clang-repl> %undo clang-repl> float x = 24 // not an error To support this, the patch extends the functionality used to recover from errors and adds functionality to recover the low-level execution infrastructure. The current implementation is based on watermarks. It exploits the fact that at each incremental input the underlying compiler infrastructure is in a valid state. We can only go N incremental inputs back to a previous valid state. We do not need and do not do any further dependency tracking. This patch was co-developed with V. Vassilev, relies on the past work of Purva Chaudhari in clang-repl and is inspired by the past work on the same feature in the Cling interpreter. Co-authored-by: Purva-Chaudhari <purva.chaudhari02@gmail.com> Co-authored-by: Vassil Vassilev <v.g.vassilev@gmail.com> Signed-off-by: Jun Zhang <jun@junz.org>
Diffstat (limited to 'clang/unittests/Interpreter/InterpreterTest.cpp')
-rw-r--r--clang/unittests/Interpreter/InterpreterTest.cpp45
1 files changed, 45 insertions, 0 deletions
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index 280c6d7f..720e30f 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -128,6 +128,51 @@ TEST(InterpreterTest, DeclsAndStatements) {
EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err)));
}
+TEST(InterpreterTest, UndoCommand) {
+ Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
+
+ // Create the diagnostic engine with unowned consumer.
+ std::string DiagnosticOutput;
+ llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
+ auto DiagPrinter = std::make_unique<TextDiagnosticPrinter>(
+ DiagnosticsOS, new DiagnosticOptions());
+
+ auto Interp = createInterpreter(ExtraArgs, DiagPrinter.get());
+
+ // Fail to undo.
+ auto Err1 = Interp->Undo();
+ EXPECT_EQ("Operation failed. Too many undos",
+ llvm::toString(std::move(Err1)));
+ auto Err2 = Interp->Parse("int foo = 42;");
+ EXPECT_TRUE(!!Err2);
+ auto Err3 = Interp->Undo(2);
+ EXPECT_EQ("Operation failed. Too many undos",
+ llvm::toString(std::move(Err3)));
+
+ // Succeed to undo.
+ auto Err4 = Interp->Parse("int x = 42;");
+ EXPECT_TRUE(!!Err4);
+ auto Err5 = Interp->Undo();
+ EXPECT_FALSE(Err5);
+ auto Err6 = Interp->Parse("int x = 24;");
+ EXPECT_TRUE(!!Err6);
+ auto Err7 = Interp->Parse("#define X 42");
+ EXPECT_TRUE(!!Err7);
+ auto Err8 = Interp->Undo();
+ EXPECT_FALSE(Err8);
+ auto Err9 = Interp->Parse("#define X 24");
+ EXPECT_TRUE(!!Err9);
+
+ // Undo input contains errors.
+ auto Err10 = Interp->Parse("int y = ;");
+ EXPECT_FALSE(!!Err10);
+ EXPECT_EQ("Parsing failed.", llvm::toString(Err10.takeError()));
+ auto Err11 = Interp->Parse("int y = 42;");
+ EXPECT_TRUE(!!Err11);
+ auto Err12 = Interp->Undo();
+ EXPECT_FALSE(Err12);
+}
+
static std::string MangleName(NamedDecl *ND) {
ASTContext &C = ND->getASTContext();
std::unique_ptr<MangleContext> MangleC(C.createMangleContext());