[PATCH] D141215: [clang-repl] Introduce Value and implement pretty printing
junaire updated this revision to Diff 508068. 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/Basic/TokenKinds.def clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Interpreter/Value.h clang/include/clang/Parse/Parser.h clang/lib/Frontend/PrintPreprocessedOutput.cpp clang/lib/Interpreter/ASTHelpers.cpp clang/lib/Interpreter/ASTHelpers.h clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Interpreter/Value.cpp clang/lib/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 @@ -139,6 +144,8 @@ auto Interp = createInterpreter(ExtraArgs, DiagPrinter.get()); + // FIXME: Now we will include some runtime headers when the first we enter + // the REPL, so this doesn't work anymore. // Fail to undo. auto Err1 = Interp->Undo(); EXPECT_EQ("Operation failed. Too many undos", @@ -276,8 +283,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 +320,31 @@ 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()); + + llvm::cantFail(Interp->ParseAndExecute("int getGlobal();")); + llvm::cantFail(Interp->ParseAndExecute("void setGlobal(int);")); + Value V2; + llvm::cantFail(Interp->ParseAndExecute("getGlobal()", )); + EXPECT_EQ(V2.getInt(), 42); + EXPECT_TRUE(V2.getType()->isIntegerType()); + + // Change the global from the compiled code. + setGlobal(43); + Value V3; + llvm::cantFail(Interp->ParseAndExecute("getGlobal()", )); + EXPECT_EQ(V3.getInt(), 43); + EXPECT_TRUE(V3.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 over the EOF token, flagging end of previous input for incremental // processing - if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) -ConsumeToken(); + if
[PATCH] D141215: [clang-repl] Introduce Value and implement pretty printing
junaire updated this revision to Diff 504038. 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/Basic/TokenKinds.def clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Interpreter/Value.h clang/include/clang/Parse/Parser.h 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/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/test/Interpreter/pretty-print.cpp clang/tools/clang-repl/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" @@ -276,8 +277,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 +314,13 @@ 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()); +} } // end anonymous namespace Index: clang/tools/clang-repl/CMakeLists.txt === --- clang/tools/clang-repl/CMakeLists.txt +++ clang/tools/clang-repl/CMakeLists.txt @@ -12,6 +12,7 @@ ) clang_target_link_libraries(clang-repl PRIVATE + clangAST clangBasic clangFrontend clangInterpreter Index: clang/test/Interpreter/pretty-print.cpp === --- /dev/null +++ clang/test/Interpreter/pretty-print.cpp @@ -0,0 +1,38 @@ +// 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.2 + +double d = 4.21; +d +// CHECK-NEXT: (double) 4.21 + +struct S{}; +S s; +s +// CHECK-NEXT: (S) [[Addr:0x.*]] + +S{} +// CHECK-NEXT: (S) [[Addr:0x.*]] + +struct SS { ~SS() {} }; +SS{} +// CHECK-NEXT: (SS) [[Addr:0x.*]] + +%quit + 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 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_input_end)) +ConsumeAnyToken(); Result = nullptr; switch (Tok.getKind()) { @@ -697,6 +698,7 @@ return false; case tok::eof: + case tok::annot_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,8 +543,16 @@ return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr); } - // Otherwise, eat the semicolon. - ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); + if
[PATCH] D141215: [clang-repl] Introduce Value and implement pretty printing
junaire updated this revision to Diff 502646. 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/Basic/TokenKinds.def clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Interpreter/Value.h clang/include/clang/Parse/Parser.h 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/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/test/Interpreter/pretty-print.cpp clang/tools/clang-repl/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" @@ -276,8 +277,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 +314,13 @@ 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()); +} } // end anonymous namespace Index: clang/tools/clang-repl/CMakeLists.txt === --- clang/tools/clang-repl/CMakeLists.txt +++ clang/tools/clang-repl/CMakeLists.txt @@ -12,6 +12,7 @@ ) clang_target_link_libraries(clang-repl PRIVATE + clangAST clangBasic clangFrontend clangInterpreter Index: clang/test/Interpreter/pretty-print.cpp === --- /dev/null +++ clang/test/Interpreter/pretty-print.cpp @@ -0,0 +1,38 @@ +// 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.2 + +double d = 4.21; +d +// CHECK-NEXT: (double) 4.21 + +struct S{}; +S s; +s +// CHECK-NEXT: (S) [[Addr:0x.*]] + +S{} +// CHECK-NEXT: (S) [[Addr:0x.*]] + +struct SS { ~SS() {} }; +SS{} +// CHECK-NEXT: (SS) [[Addr:0x.*]] + +%quit + 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 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_input_end)) +ConsumeAnyToken(); Result = nullptr; switch (Tok.getKind()) { @@ -697,6 +698,7 @@ return false; case tok::eof: + case tok::annot_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,8 +543,16 @@ return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr); } - // Otherwise, eat the semicolon. - ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); + if
[PATCH] D141215: [clang-repl] Introduce Value and implement pretty printing
junaire updated this revision to Diff 502407. 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/Basic/TokenKinds.def clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Interpreter/Value.h clang/include/clang/Parse/Parser.h 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/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/test/Interpreter/pretty-print.cpp clang/tools/clang-repl/CMakeLists.txt clang/tools/clang-repl/ClangRepl.cpp Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -66,6 +66,32 @@ return (Errs || HasError) ? EXIT_FAILURE : EXIT_SUCCESS; } +static void DeclareMagicFunctions(clang::Interpreter ) { + std::vector MagicFunctions = { + "void __InterpreterSetValueNoAlloc(void*, void*, void*, bool);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, signed char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long " + "long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, float);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, double);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, void*);", + "void* __InterpreterSetValueWithAlloc(void*, void*, void*);"}; + + for (llvm::StringRef Function : MagicFunctions) { +llvm::cantFail(Interp.ParseAndExecute(Function)); + } + llvm::cantFail(Interp.ParseAndExecute("#include ")); +} + llvm::ExitOnError ExitOnErr; int main(int argc, const char **argv) { ExitOnErr.setBanner("clang-repl: "); @@ -110,6 +136,7 @@ bool HasError = false; + DeclareMagicFunctions(*Interp); if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); // FIXME: Add LE.setListCompleter Index: clang/tools/clang-repl/CMakeLists.txt === --- clang/tools/clang-repl/CMakeLists.txt +++ clang/tools/clang-repl/CMakeLists.txt @@ -12,6 +12,7 @@ ) clang_target_link_libraries(clang-repl PRIVATE + clangAST clangBasic clangFrontend clangInterpreter Index: clang/test/Interpreter/pretty-print.cpp === --- /dev/null +++ clang/test/Interpreter/pretty-print.cpp @@ -0,0 +1,38 @@ +// 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.2 + +double d = 4.21; +d +// CHECK-NEXT: (double) 4.21 + +struct S{}; +S s; +s +// CHECK-NEXT: (S) [[Addr:0x.*]] + +S{} +// CHECK-NEXT: (S) [[Addr:0x.*]] + +struct SS { ~SS() {} }; +SS{} +// CHECK-NEXT: (SS) [[Addr:0x.*]] + +%quit + 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 over the EOF token, flagging end of previous input for incremental // processing - if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) -ConsumeToken(); + if (PP.isIncrementalProcessingEnabled() &&
[PATCH] D141215: [clang-repl] Introduce Value and implement pretty printing
junaire updated this revision to Diff 502406. junaire added a comment. Fix patch application failed Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D141215/new/ https://reviews.llvm.org/D141215 Files: 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/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/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/test/Interpreter/pretty-print.cpp clang/tools/clang-repl/CMakeLists.txt clang/tools/clang-repl/ClangRepl.cpp Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -66,6 +66,32 @@ return (Errs || HasError) ? EXIT_FAILURE : EXIT_SUCCESS; } +static void DeclareMagicFunctions(clang::Interpreter ) { + std::vector MagicFunctions = { + "void __InterpreterSetValueNoAlloc(void*, void*, void*, bool);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, signed char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long " + "long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, float);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, double);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, void*);", + "void* __InterpreterSetValueWithAlloc(void*, void*, void*);"}; + + for (llvm::StringRef Function : MagicFunctions) { +llvm::cantFail(Interp.ParseAndExecute(Function)); + } + llvm::cantFail(Interp.ParseAndExecute("#include ")); +} + llvm::ExitOnError ExitOnErr; int main(int argc, const char **argv) { ExitOnErr.setBanner("clang-repl: "); @@ -110,6 +136,7 @@ bool HasError = false; + DeclareMagicFunctions(*Interp); if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); // FIXME: Add LE.setListCompleter Index: clang/tools/clang-repl/CMakeLists.txt === --- clang/tools/clang-repl/CMakeLists.txt +++ clang/tools/clang-repl/CMakeLists.txt @@ -12,6 +12,7 @@ ) clang_target_link_libraries(clang-repl PRIVATE + clangAST clangBasic clangFrontend clangInterpreter Index: clang/test/Interpreter/pretty-print.cpp === --- /dev/null +++ clang/test/Interpreter/pretty-print.cpp @@ -0,0 +1,38 @@ +// 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.2 + +double d = 4.21; +d +// CHECK-NEXT: (double) 4.21 + +struct S{}; +S s; +s +// CHECK-NEXT: (S) [[Addr:0x.*]] + +S{} +// CHECK-NEXT: (S) [[Addr:0x.*]] + +struct SS { ~SS() {} }; +SS{} +// CHECK-NEXT: (SS) [[Addr:0x.*]] + +%quit + 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 over the EOF token, flagging end of previous input for incremental // processing - if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) -ConsumeToken(); + if (PP.isIncrementalProcessingEnabled() &&
[PATCH] D141215: [clang-repl] Introduce Value and implement pretty printing
junaire updated this revision to Diff 502405. junaire added a comment. Prefer one 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/Basic/TokenKinds.def clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Interpreter/Value.h clang/include/clang/Parse/Parser.h 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/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/test/Interpreter/pretty-print.cpp clang/tools/clang-repl/CMakeLists.txt clang/tools/clang-repl/ClangRepl.cpp Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -66,6 +66,32 @@ return (Errs || HasError) ? EXIT_FAILURE : EXIT_SUCCESS; } +static void DeclareMagicFunctions(clang::Interpreter ) { + std::vector MagicFunctions = { + "void __InterpreterSetValueNoAlloc(void*, void*, void*, bool);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, signed char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long " + "long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, float);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, double);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, void*);", + "void* __InterpreterSetValueWithAlloc(void*, void*, void*);"}; + + for (llvm::StringRef Function : MagicFunctions) { +llvm::cantFail(Interp.ParseAndExecute(Function)); + } + llvm::cantFail(Interp.ParseAndExecute("#include ")); +} + llvm::ExitOnError ExitOnErr; int main(int argc, const char **argv) { ExitOnErr.setBanner("clang-repl: "); @@ -110,6 +136,7 @@ bool HasError = false; + DeclareMagicFunctions(*Interp); if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); // FIXME: Add LE.setListCompleter Index: clang/tools/clang-repl/CMakeLists.txt === --- clang/tools/clang-repl/CMakeLists.txt +++ clang/tools/clang-repl/CMakeLists.txt @@ -12,6 +12,7 @@ ) clang_target_link_libraries(clang-repl PRIVATE + clangAST clangBasic clangFrontend clangInterpreter Index: clang/test/Interpreter/pretty-print.cpp === --- /dev/null +++ clang/test/Interpreter/pretty-print.cpp @@ -0,0 +1,38 @@ +// 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.2 + +double d = 4.21; +d +// CHECK-NEXT: (double) 4.21 + +struct S{}; +S s; +s +// CHECK-NEXT: (S) [[Addr:0x.*]] + +S{} +// CHECK-NEXT: (S) [[Addr:0x.*]] + +struct SS { ~SS() {} }; +SS{} +// CHECK-NEXT: (SS) [[Addr:0x.*]] + +%quit + 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 over the EOF token, flagging end of previous input for incremental // processing - if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) -ConsumeToken(); + if (PP.isIncrementalProcessingEnabled() &&
[PATCH] D141215: [clang-repl] Introduce Value and implement pretty printing
junaire updated this revision to Diff 502402. 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/Interpreter/Interpreter.h clang/include/clang/Interpreter/Value.h clang/include/clang/Parse/Parser.h clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Interpreter/Value.cpp clang/lib/Parse/ParseStmt.cpp clang/test/Interpreter/pretty-print.cpp clang/tools/clang-repl/CMakeLists.txt clang/tools/clang-repl/ClangRepl.cpp Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -66,6 +66,32 @@ return (Errs || HasError) ? EXIT_FAILURE : EXIT_SUCCESS; } +static void DeclareMagicFunctions(clang::Interpreter ) { + std::vector MagicFunctions = { + "void __InterpreterSetValueNoAlloc(void*, void*, void*, bool);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, signed char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long " + "long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, float);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, double);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, void*);", + "void* __InterpreterSetValueWithAlloc(void*, void*, void*);"}; + + for (llvm::StringRef Function : MagicFunctions) { +llvm::cantFail(Interp.ParseAndExecute(Function)); + } + llvm::cantFail(Interp.ParseAndExecute("#include ")); +} + llvm::ExitOnError ExitOnErr; int main(int argc, const char **argv) { ExitOnErr.setBanner("clang-repl: "); @@ -110,6 +136,7 @@ bool HasError = false; + DeclareMagicFunctions(*Interp); if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); // FIXME: Add LE.setListCompleter Index: clang/tools/clang-repl/CMakeLists.txt === --- clang/tools/clang-repl/CMakeLists.txt +++ clang/tools/clang-repl/CMakeLists.txt @@ -12,6 +12,7 @@ ) clang_target_link_libraries(clang-repl PRIVATE + clangAST clangBasic clangFrontend clangInterpreter Index: clang/test/Interpreter/pretty-print.cpp === --- /dev/null +++ clang/test/Interpreter/pretty-print.cpp @@ -0,0 +1,38 @@ +// 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.2 + +double d = 4.21; +d +// CHECK-NEXT: (double) 4.21 + +struct S{}; +S s; +s +// CHECK-NEXT: (S) [[Addr:0x.*]] + +S{} +// CHECK-NEXT: (S) [[Addr:0x.*]] + +struct SS { ~SS() {} }; +SS{} +// CHECK-NEXT: (SS) [[Addr:0x.*]] + +%quit + Index: clang/lib/Parse/ParseStmt.cpp === --- clang/lib/Parse/ParseStmt.cpp +++ clang/lib/Parse/ParseStmt.cpp @@ -543,8 +543,16 @@ return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr); } - // Otherwise, eat the semicolon. - ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); + if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::annot_input_end)) { +// 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. +ConsumeAnyToken(); +setPrettyPrintMode(); + } else { +// Otherwise, eat the semicolon. +ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); + } return handleExprStmt(Expr, StmtCtx); } Index: clang/lib/Interpreter/Value.cpp === --- /dev/null +++ clang/lib/Interpreter/Value.cpp @@
[PATCH] D141215: [clang-repl] Introduce Value and implement pretty printing
junaire updated this revision to Diff 501365. junaire added a comment. Add more tests Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D141215/new/ https://reviews.llvm.org/D141215 Files: clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Interpreter/Value.h clang/include/clang/Parse/Parser.h clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Interpreter/Value.cpp clang/lib/Parse/ParseStmt.cpp clang/lib/Parse/Parser.cpp clang/test/Interpreter/pretty-print.cpp clang/tools/clang-repl/CMakeLists.txt clang/tools/clang-repl/ClangRepl.cpp Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -66,6 +66,32 @@ return (Errs || HasError) ? EXIT_FAILURE : EXIT_SUCCESS; } +static void DeclareMagicFunctions(clang::Interpreter ) { + std::vector MagicFunctions = { + "void __InterpreterSetValueNoAlloc(void*, void*, void*, bool);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, signed char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long " + "long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, float);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, double);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, void*);", + "void* __InterpreterSetValueWithAlloc(void*, void*, void*);"}; + + for (llvm::StringRef Function : MagicFunctions) { +llvm::cantFail(Interp.ParseAndExecute(Function)); + } + llvm::cantFail(Interp.ParseAndExecute("#include ")); +} + llvm::ExitOnError ExitOnErr; int main(int argc, const char **argv) { ExitOnErr.setBanner("clang-repl: "); @@ -110,6 +136,7 @@ bool HasError = false; + DeclareMagicFunctions(*Interp); if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); // FIXME: Add LE.setListCompleter Index: clang/tools/clang-repl/CMakeLists.txt === --- clang/tools/clang-repl/CMakeLists.txt +++ clang/tools/clang-repl/CMakeLists.txt @@ -12,6 +12,7 @@ ) clang_target_link_libraries(clang-repl PRIVATE + clangAST clangBasic clangFrontend clangInterpreter Index: clang/test/Interpreter/pretty-print.cpp === --- /dev/null +++ clang/test/Interpreter/pretty-print.cpp @@ -0,0 +1,38 @@ +// 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.2 + +double d = 4.21; +d +// CHECK-NEXT: (double) 4.21 + +struct S{}; +S s; +s +// CHECK-NEXT: (S) [[Addr:0x.*]] + +S{} +// CHECK-NEXT: (S) [[Addr:0x.*]] + +struct SS { ~SS() {} }; +SS{} +// CHECK-NEXT: (SS) [[Addr:0x.*]] + +%quit + Index: clang/lib/Parse/Parser.cpp === --- clang/lib/Parse/Parser.cpp +++ clang/lib/Parse/Parser.cpp @@ -154,10 +154,20 @@ return true; } -bool Parser::ExpectAndConsumeSemi(unsigned DiagID, StringRef TokenUsed) { +bool Parser::ExpectAndConsumeSemi(unsigned DiagID, StringRef TokenUsed, + bool IsTopExpr) { if (TryConsumeToken(tok::semi)) return false; + // If this is in the incremental C++ mode, then it means we need to pretty + // print this expression. Thus, let's pretend we have this semi and continue + // parsing. + if (PP.isIncrementalProcessingEnabled() && IsTopExpr && + DiagID == diag::err_expected_semi_after_expr) { +setPrettyPrintMode(); +return false; + } + if (Tok.is(tok::code_completion)) { handleUnexpectedCodeCompletionToken(); return false; Index: clang/lib/Parse/ParseStmt.cpp
[PATCH] D141215: [clang-repl] Introduce Value and implement pretty printing
junaire updated this revision to Diff 501363. junaire edited the summary of this revision. junaire added a comment. Remove extra includes Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D141215/new/ https://reviews.llvm.org/D141215 Files: clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Interpreter/Value.h clang/include/clang/Parse/Parser.h clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Interpreter/Value.cpp clang/lib/Parse/ParseStmt.cpp clang/lib/Parse/Parser.cpp clang/test/Interpreter/pretty-print.cpp clang/tools/clang-repl/CMakeLists.txt clang/tools/clang-repl/ClangRepl.cpp Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -66,6 +66,32 @@ return (Errs || HasError) ? EXIT_FAILURE : EXIT_SUCCESS; } +static void DeclareMagicFunctions(clang::Interpreter ) { + std::vector MagicFunctions = { + "void __InterpreterSetValueNoAlloc(void*, void*, void*, bool);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, signed char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, long long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned char);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned short);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned int);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, unsigned long " + "long);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, float);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, double);", + "void __InterpreterSetValueNoAlloc(void*, void*, void*, void*);", + "void* __InterpreterSetValueWithAlloc(void*, void*, void*);"}; + + for (llvm::StringRef Function : MagicFunctions) { +llvm::cantFail(Interp.ParseAndExecute(Function)); + } + llvm::cantFail(Interp.ParseAndExecute("#include ")); +} + llvm::ExitOnError ExitOnErr; int main(int argc, const char **argv) { ExitOnErr.setBanner("clang-repl: "); @@ -110,6 +136,7 @@ bool HasError = false; + DeclareMagicFunctions(*Interp); if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); // FIXME: Add LE.setListCompleter Index: clang/tools/clang-repl/CMakeLists.txt === --- clang/tools/clang-repl/CMakeLists.txt +++ clang/tools/clang-repl/CMakeLists.txt @@ -12,6 +12,7 @@ ) clang_target_link_libraries(clang-repl PRIVATE + clangAST clangBasic clangFrontend clangInterpreter Index: clang/test/Interpreter/pretty-print.cpp === --- /dev/null +++ clang/test/Interpreter/pretty-print.cpp @@ -0,0 +1,23 @@ +// RUN: clang-repl "int i = 10;" 'extern "C" int printf(const char*,...);' \ +// RUN:'auto r1 = printf("i = %d\n", i);' | FileCheck --check-prefix=CHECK-DRIVER %s +// UNSUPPORTED: system-aix +// CHECK-DRIVER: i = 10 +// RUN: cat %s | clang-repl | FileCheck %s +char c = 'a'; +c +// CHECK: (char) a + +int x = 42; +x +// CHECK-NEXT: (int) 42 + +float f = 4.2f; +f +// CHECK-NEXT: (float) 4.2 + +double d = 4.21; +d +// CHECK-NEXT: (double) 4.21 + +%quit + Index: clang/lib/Parse/Parser.cpp === --- clang/lib/Parse/Parser.cpp +++ clang/lib/Parse/Parser.cpp @@ -154,10 +154,20 @@ return true; } -bool Parser::ExpectAndConsumeSemi(unsigned DiagID, StringRef TokenUsed) { +bool Parser::ExpectAndConsumeSemi(unsigned DiagID, StringRef TokenUsed, + bool IsTopExpr) { if (TryConsumeToken(tok::semi)) return false; + // If this is in the incremental C++ mode, then it means we need to pretty + // print this expression. Thus, let's pretend we have this semi and continue + // parsing. + if (PP.isIncrementalProcessingEnabled() && IsTopExpr && + DiagID == diag::err_expected_semi_after_expr) { +setPrettyPrintMode(); +return false; + } + if (Tok.is(tok::code_completion)) { handleUnexpectedCodeCompletionToken(); return false; Index: clang/lib/Parse/ParseStmt.cpp === --- clang/lib/Parse/ParseStmt.cpp +++ clang/lib/Parse/ParseStmt.cpp @@ -542,9 +542,9 @@ // Recover parsing as a