1+ // ===--- IncrementalAction.h - Incremental Frontend Action -*- C++ -*-===//
2+ //
3+ // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+ // See https://llvm.org/LICENSE.txt for license information.
5+ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+ //
7+ // ===----------------------------------------------------------------------===//
8+
9+ #include " IncrementalAction.h"
10+
11+ #include " clang/AST/ASTConsumer.h"
12+ #include " clang/CodeGen/CodeGenAction.h"
13+ #include " clang/Frontend/CompilerInstance.h"
14+ #include " clang/Frontend/FrontendOptions.h"
15+ #include " clang/FrontendTool/Utils.h"
16+ #include " clang/Interpreter/Interpreter.h"
17+ #include " clang/Sema/Sema.h"
18+ #include " llvm/Support/Error.h"
19+ #include " llvm/Support/ErrorHandling.h"
20+
21+ namespace clang {
22+ IncrementalAction::IncrementalAction (CompilerInstance &CI,
23+ llvm::LLVMContext &LLVMCtx,
24+ llvm::Error &Err, Interpreter &I,
25+ std::unique_ptr<ASTConsumer> Consumer)
26+ : WrapperFrontendAction([&]() {
27+ llvm::ErrorAsOutParameter EAO (&Err);
28+ std::unique_ptr<FrontendAction> Act;
29+ switch (CI.getFrontendOpts ().ProgramAction ) {
30+ default :
31+ Err = llvm::createStringError (
32+ std::errc::state_not_recoverable,
33+ " Driver initialization failed. "
34+ " Incremental mode for action %d is not supported" ,
35+ CI.getFrontendOpts ().ProgramAction );
36+ return Act;
37+ case frontend::ASTDump:
38+ case frontend::ASTPrint:
39+ case frontend::ParseSyntaxOnly:
40+ Act = CreateFrontendAction (CI);
41+ break ;
42+ case frontend::PluginAction:
43+ case frontend::EmitAssembly:
44+ case frontend::EmitBC:
45+ case frontend::EmitObj:
46+ case frontend::PrintPreprocessedInput:
47+ case frontend::EmitLLVMOnly:
48+ Act.reset (new EmitLLVMOnlyAction (&LLVMCtx));
49+ break ;
50+ }
51+ return Act;
52+ }()),
53+ Interp (I), Consumer(std::move(Consumer)) {}
54+
55+ std::unique_ptr<ASTConsumer>
56+ IncrementalAction::CreateASTConsumer (CompilerInstance &CI, StringRef InFile) {
57+ std::unique_ptr<ASTConsumer> C =
58+ WrapperFrontendAction::CreateASTConsumer (CI, InFile);
59+
60+ if (Consumer) {
61+ std::vector<std::unique_ptr<ASTConsumer>> Cs;
62+ Cs.push_back (std::move (Consumer));
63+ Cs.push_back (std::move (C));
64+ return std::make_unique<MultiplexConsumer>(std::move (Cs));
65+ }
66+
67+ return std::make_unique<InProcessPrintingASTConsumer>(std::move (C), Interp);
68+ }
69+
70+ void IncrementalAction::ExecuteAction () {
71+ WrapperFrontendAction::ExecuteAction ();
72+ getCompilerInstance ().getSema ().CurContext = nullptr ;
73+ }
74+
75+ void IncrementalAction::EndSourceFile () {
76+ if (IsTerminating && getWrapped ())
77+ WrapperFrontendAction::EndSourceFile ();
78+ }
79+
80+ void IncrementalAction::FinalizeAction () {
81+ assert (!IsTerminating && " Already finalized!" );
82+ IsTerminating = true ;
83+ EndSourceFile ();
84+ }
85+
86+ InProcessPrintingASTConsumer::InProcessPrintingASTConsumer (
87+ std::unique_ptr<ASTConsumer> C, Interpreter &I)
88+ : MultiplexConsumer(std::move(C)), Interp(I) {}
89+
90+ bool InProcessPrintingASTConsumer::HandleTopLevelDecl (DeclGroupRef DGR) {
91+ if (DGR.isNull ())
92+ return true ;
93+
94+ for (Decl *D : DGR)
95+ if (auto *TLSD = llvm::dyn_cast<TopLevelStmtDecl>(D))
96+ if (TLSD && TLSD->isSemiMissing ()) {
97+ auto ExprOrErr =
98+ Interp.ExtractValueFromExpr (cast<Expr>(TLSD->getStmt ()));
99+ if (llvm::Error E = ExprOrErr.takeError ()) {
100+ llvm::logAllUnhandledErrors (std::move (E), llvm::errs (),
101+ " Value printing failed: " );
102+ return false ; // abort parsing
103+ }
104+ TLSD->setStmt (*ExprOrErr);
105+ }
106+
107+ return MultiplexConsumer::HandleTopLevelDecl (DGR);
108+ }
109+
110+ } // namespace clang
0 commit comments