[clang] [clang-repl] Simplify the value printing logic to enable out-of-process. (PR #107737)

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 20 06:39:53 PDT 2024


================
@@ -241,28 +244,180 @@ IncrementalCompilerBuilder::CreateCudaHost() {
   return IncrementalCompilerBuilder::createCuda(false);
 }
 
-Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
+class InProcessPrintingASTConsumer final : public MultiplexConsumer {
+  Interpreter &Interp;
+
+public:
+  InProcessPrintingASTConsumer(std::unique_ptr<ASTConsumer> C, Interpreter &I)
+      : MultiplexConsumer(std::move(C)), Interp(I) {}
+  bool HandleTopLevelDecl(DeclGroupRef DGR) override final {
+    if (DGR.isNull())
+      return true;
+
+    for (Decl *D : DGR)
+      if (auto *TLSD = llvm::dyn_cast<TopLevelStmtDecl>(D))
+        if (TLSD && TLSD->isSemiMissing()) {
+          auto ExprOrErr =
+              Interp.ExtractValueFromExpr(cast<Expr>(TLSD->getStmt()));
+          if (llvm::Error E = ExprOrErr.takeError()) {
+            llvm::logAllUnhandledErrors(std::move(E), llvm::errs(),
+                                        "Value printing failed: ");
+            return false; // abort parsing
+          }
+          TLSD->setStmt(*ExprOrErr);
+        }
+
+    return MultiplexConsumer::HandleTopLevelDecl(DGR);
+  }
+};
+
+/// A custom action enabling the incremental processing functionality.
+///
+/// The usual \p FrontendAction expects one call to ExecuteAction and once it
+/// sees a call to \p EndSourceFile it deletes some of the important objects
+/// such as \p Preprocessor and \p Sema assuming no further input will come.
+///
+/// \p IncrementalAction ensures it keep its underlying action's objects alive
+/// as long as the \p IncrementalParser needs them.
+///
+class IncrementalAction : public WrapperFrontendAction {
+private:
+  bool IsTerminating = false;
+  Interpreter &Interp;
+  std::unique_ptr<ASTConsumer> Consumer;
+
+public:
+  IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx,
+                    llvm::Error &Err, Interpreter &I,
+                    std::unique_ptr<ASTConsumer> Consumer = nullptr)
+      : WrapperFrontendAction([&]() {
+          llvm::ErrorAsOutParameter EAO(&Err);
+          std::unique_ptr<FrontendAction> Act;
+          switch (CI.getFrontendOpts().ProgramAction) {
+          default:
+            Err = llvm::createStringError(
+                std::errc::state_not_recoverable,
+                "Driver initialization failed. "
+                "Incremental mode for action %d is not supported",
+                CI.getFrontendOpts().ProgramAction);
+            return Act;
+          case frontend::ASTDump:
+            [[fallthrough]];
+          case frontend::ASTPrint:
+            [[fallthrough]];
+          case frontend::ParseSyntaxOnly:
+            Act = CreateFrontendAction(CI);
+            break;
+          case frontend::PluginAction:
+            [[fallthrough]];
+          case frontend::EmitAssembly:
+            [[fallthrough]];
+          case frontend::EmitBC:
+            [[fallthrough]];
+          case frontend::EmitObj:
+            [[fallthrough]];
+          case frontend::PrintPreprocessedInput:
+            [[fallthrough]];
----------------
AaronBallman wrote:

```suggestion
          case frontend::PluginAction:
          case frontend::EmitAssembly:
          case frontend::EmitBC:
          case frontend::EmitObj:
          case frontend::PrintPreprocessedInput:
```
You only need the `fallthrough` attribute when the cases are not immediately adjacent to one another (basically, one of the cases has to do something, otherwise fallthrough is very much expected).

https://github.com/llvm/llvm-project/pull/107737


More information about the cfe-commits mailing list