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