1f4a2713aSLionel Sambuc //===--- FrontendAction.cpp -----------------------------------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc
10f4a2713aSLionel Sambuc #include "clang/Frontend/FrontendAction.h"
11f4a2713aSLionel Sambuc #include "clang/AST/ASTConsumer.h"
12f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
13f4a2713aSLionel Sambuc #include "clang/AST/DeclGroup.h"
14f4a2713aSLionel Sambuc #include "clang/Frontend/ASTUnit.h"
15f4a2713aSLionel Sambuc #include "clang/Frontend/CompilerInstance.h"
16f4a2713aSLionel Sambuc #include "clang/Frontend/FrontendDiagnostic.h"
17f4a2713aSLionel Sambuc #include "clang/Frontend/FrontendPluginRegistry.h"
18f4a2713aSLionel Sambuc #include "clang/Frontend/LayoutOverrideSource.h"
19f4a2713aSLionel Sambuc #include "clang/Frontend/MultiplexConsumer.h"
20*0a6a1f1dSLionel Sambuc #include "clang/Frontend/Utils.h"
21f4a2713aSLionel Sambuc #include "clang/Lex/HeaderSearch.h"
22f4a2713aSLionel Sambuc #include "clang/Lex/Preprocessor.h"
23f4a2713aSLionel Sambuc #include "clang/Parse/ParseAST.h"
24f4a2713aSLionel Sambuc #include "clang/Serialization/ASTDeserializationListener.h"
25f4a2713aSLionel Sambuc #include "clang/Serialization/ASTReader.h"
26f4a2713aSLionel Sambuc #include "clang/Serialization/GlobalModuleIndex.h"
27f4a2713aSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
28f4a2713aSLionel Sambuc #include "llvm/Support/FileSystem.h"
29f4a2713aSLionel Sambuc #include "llvm/Support/MemoryBuffer.h"
30f4a2713aSLionel Sambuc #include "llvm/Support/Timer.h"
31f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
32*0a6a1f1dSLionel Sambuc #include <system_error>
33f4a2713aSLionel Sambuc using namespace clang;
34f4a2713aSLionel Sambuc
35*0a6a1f1dSLionel Sambuc template class llvm::Registry<clang::PluginASTAction>;
36*0a6a1f1dSLionel Sambuc
37f4a2713aSLionel Sambuc namespace {
38f4a2713aSLionel Sambuc
39f4a2713aSLionel Sambuc class DelegatingDeserializationListener : public ASTDeserializationListener {
40f4a2713aSLionel Sambuc ASTDeserializationListener *Previous;
41*0a6a1f1dSLionel Sambuc bool DeletePrevious;
42f4a2713aSLionel Sambuc
43f4a2713aSLionel Sambuc public:
DelegatingDeserializationListener(ASTDeserializationListener * Previous,bool DeletePrevious)44f4a2713aSLionel Sambuc explicit DelegatingDeserializationListener(
45*0a6a1f1dSLionel Sambuc ASTDeserializationListener *Previous, bool DeletePrevious)
46*0a6a1f1dSLionel Sambuc : Previous(Previous), DeletePrevious(DeletePrevious) {}
~DelegatingDeserializationListener()47*0a6a1f1dSLionel Sambuc virtual ~DelegatingDeserializationListener() {
48*0a6a1f1dSLionel Sambuc if (DeletePrevious)
49*0a6a1f1dSLionel Sambuc delete Previous;
50*0a6a1f1dSLionel Sambuc }
51f4a2713aSLionel Sambuc
ReaderInitialized(ASTReader * Reader)52*0a6a1f1dSLionel Sambuc void ReaderInitialized(ASTReader *Reader) override {
53f4a2713aSLionel Sambuc if (Previous)
54f4a2713aSLionel Sambuc Previous->ReaderInitialized(Reader);
55f4a2713aSLionel Sambuc }
IdentifierRead(serialization::IdentID ID,IdentifierInfo * II)56*0a6a1f1dSLionel Sambuc void IdentifierRead(serialization::IdentID ID,
57*0a6a1f1dSLionel Sambuc IdentifierInfo *II) override {
58f4a2713aSLionel Sambuc if (Previous)
59f4a2713aSLionel Sambuc Previous->IdentifierRead(ID, II);
60f4a2713aSLionel Sambuc }
TypeRead(serialization::TypeIdx Idx,QualType T)61*0a6a1f1dSLionel Sambuc void TypeRead(serialization::TypeIdx Idx, QualType T) override {
62f4a2713aSLionel Sambuc if (Previous)
63f4a2713aSLionel Sambuc Previous->TypeRead(Idx, T);
64f4a2713aSLionel Sambuc }
DeclRead(serialization::DeclID ID,const Decl * D)65*0a6a1f1dSLionel Sambuc void DeclRead(serialization::DeclID ID, const Decl *D) override {
66f4a2713aSLionel Sambuc if (Previous)
67f4a2713aSLionel Sambuc Previous->DeclRead(ID, D);
68f4a2713aSLionel Sambuc }
SelectorRead(serialization::SelectorID ID,Selector Sel)69*0a6a1f1dSLionel Sambuc void SelectorRead(serialization::SelectorID ID, Selector Sel) override {
70f4a2713aSLionel Sambuc if (Previous)
71f4a2713aSLionel Sambuc Previous->SelectorRead(ID, Sel);
72f4a2713aSLionel Sambuc }
MacroDefinitionRead(serialization::PreprocessedEntityID PPID,MacroDefinition * MD)73*0a6a1f1dSLionel Sambuc void MacroDefinitionRead(serialization::PreprocessedEntityID PPID,
74*0a6a1f1dSLionel Sambuc MacroDefinition *MD) override {
75f4a2713aSLionel Sambuc if (Previous)
76f4a2713aSLionel Sambuc Previous->MacroDefinitionRead(PPID, MD);
77f4a2713aSLionel Sambuc }
78f4a2713aSLionel Sambuc };
79f4a2713aSLionel Sambuc
80f4a2713aSLionel Sambuc /// \brief Dumps deserialized declarations.
81f4a2713aSLionel Sambuc class DeserializedDeclsDumper : public DelegatingDeserializationListener {
82f4a2713aSLionel Sambuc public:
DeserializedDeclsDumper(ASTDeserializationListener * Previous,bool DeletePrevious)83*0a6a1f1dSLionel Sambuc explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous,
84*0a6a1f1dSLionel Sambuc bool DeletePrevious)
85*0a6a1f1dSLionel Sambuc : DelegatingDeserializationListener(Previous, DeletePrevious) {}
86f4a2713aSLionel Sambuc
DeclRead(serialization::DeclID ID,const Decl * D)87*0a6a1f1dSLionel Sambuc void DeclRead(serialization::DeclID ID, const Decl *D) override {
88f4a2713aSLionel Sambuc llvm::outs() << "PCH DECL: " << D->getDeclKindName();
89f4a2713aSLionel Sambuc if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
90f4a2713aSLionel Sambuc llvm::outs() << " - " << *ND;
91f4a2713aSLionel Sambuc llvm::outs() << "\n";
92f4a2713aSLionel Sambuc
93f4a2713aSLionel Sambuc DelegatingDeserializationListener::DeclRead(ID, D);
94f4a2713aSLionel Sambuc }
95f4a2713aSLionel Sambuc };
96f4a2713aSLionel Sambuc
97f4a2713aSLionel Sambuc /// \brief Checks deserialized declarations and emits error if a name
98f4a2713aSLionel Sambuc /// matches one given in command-line using -error-on-deserialized-decl.
99f4a2713aSLionel Sambuc class DeserializedDeclsChecker : public DelegatingDeserializationListener {
100f4a2713aSLionel Sambuc ASTContext &Ctx;
101f4a2713aSLionel Sambuc std::set<std::string> NamesToCheck;
102f4a2713aSLionel Sambuc
103f4a2713aSLionel Sambuc public:
DeserializedDeclsChecker(ASTContext & Ctx,const std::set<std::string> & NamesToCheck,ASTDeserializationListener * Previous,bool DeletePrevious)104f4a2713aSLionel Sambuc DeserializedDeclsChecker(ASTContext &Ctx,
105f4a2713aSLionel Sambuc const std::set<std::string> &NamesToCheck,
106*0a6a1f1dSLionel Sambuc ASTDeserializationListener *Previous,
107*0a6a1f1dSLionel Sambuc bool DeletePrevious)
108*0a6a1f1dSLionel Sambuc : DelegatingDeserializationListener(Previous, DeletePrevious), Ctx(Ctx),
109*0a6a1f1dSLionel Sambuc NamesToCheck(NamesToCheck) {}
110f4a2713aSLionel Sambuc
DeclRead(serialization::DeclID ID,const Decl * D)111*0a6a1f1dSLionel Sambuc void DeclRead(serialization::DeclID ID, const Decl *D) override {
112f4a2713aSLionel Sambuc if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
113f4a2713aSLionel Sambuc if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) {
114f4a2713aSLionel Sambuc unsigned DiagID
115f4a2713aSLionel Sambuc = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error,
116f4a2713aSLionel Sambuc "%0 was deserialized");
117f4a2713aSLionel Sambuc Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID)
118f4a2713aSLionel Sambuc << ND->getNameAsString();
119f4a2713aSLionel Sambuc }
120f4a2713aSLionel Sambuc
121f4a2713aSLionel Sambuc DelegatingDeserializationListener::DeclRead(ID, D);
122f4a2713aSLionel Sambuc }
123f4a2713aSLionel Sambuc };
124f4a2713aSLionel Sambuc
125f4a2713aSLionel Sambuc } // end anonymous namespace
126f4a2713aSLionel Sambuc
FrontendAction()127*0a6a1f1dSLionel Sambuc FrontendAction::FrontendAction() : Instance(nullptr) {}
128f4a2713aSLionel Sambuc
~FrontendAction()129f4a2713aSLionel Sambuc FrontendAction::~FrontendAction() {}
130f4a2713aSLionel Sambuc
setCurrentInput(const FrontendInputFile & CurrentInput,std::unique_ptr<ASTUnit> AST)131f4a2713aSLionel Sambuc void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput,
132*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTUnit> AST) {
133f4a2713aSLionel Sambuc this->CurrentInput = CurrentInput;
134*0a6a1f1dSLionel Sambuc CurrentASTUnit = std::move(AST);
135f4a2713aSLionel Sambuc }
136f4a2713aSLionel Sambuc
137*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer>
CreateWrappedASTConsumer(CompilerInstance & CI,StringRef InFile)138*0a6a1f1dSLionel Sambuc FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
139f4a2713aSLionel Sambuc StringRef InFile) {
140*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer> Consumer = CreateASTConsumer(CI, InFile);
141f4a2713aSLionel Sambuc if (!Consumer)
142*0a6a1f1dSLionel Sambuc return nullptr;
143f4a2713aSLionel Sambuc
144f4a2713aSLionel Sambuc if (CI.getFrontendOpts().AddPluginActions.size() == 0)
145f4a2713aSLionel Sambuc return Consumer;
146f4a2713aSLionel Sambuc
147f4a2713aSLionel Sambuc // Make sure the non-plugin consumer is first, so that plugins can't
148f4a2713aSLionel Sambuc // modifiy the AST.
149*0a6a1f1dSLionel Sambuc std::vector<std::unique_ptr<ASTConsumer>> Consumers;
150*0a6a1f1dSLionel Sambuc Consumers.push_back(std::move(Consumer));
151f4a2713aSLionel Sambuc
152f4a2713aSLionel Sambuc for (size_t i = 0, e = CI.getFrontendOpts().AddPluginActions.size();
153f4a2713aSLionel Sambuc i != e; ++i) {
154f4a2713aSLionel Sambuc // This is O(|plugins| * |add_plugins|), but since both numbers are
155f4a2713aSLionel Sambuc // way below 50 in practice, that's ok.
156f4a2713aSLionel Sambuc for (FrontendPluginRegistry::iterator
157f4a2713aSLionel Sambuc it = FrontendPluginRegistry::begin(),
158f4a2713aSLionel Sambuc ie = FrontendPluginRegistry::end();
159f4a2713aSLionel Sambuc it != ie; ++it) {
160*0a6a1f1dSLionel Sambuc if (it->getName() != CI.getFrontendOpts().AddPluginActions[i])
161*0a6a1f1dSLionel Sambuc continue;
162*0a6a1f1dSLionel Sambuc std::unique_ptr<PluginASTAction> P = it->instantiate();
163f4a2713aSLionel Sambuc if (P->ParseArgs(CI, CI.getFrontendOpts().AddPluginArgs[i]))
164*0a6a1f1dSLionel Sambuc Consumers.push_back(P->CreateASTConsumer(CI, InFile));
165f4a2713aSLionel Sambuc }
166f4a2713aSLionel Sambuc }
167f4a2713aSLionel Sambuc
168*0a6a1f1dSLionel Sambuc return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
169f4a2713aSLionel Sambuc }
170f4a2713aSLionel Sambuc
BeginSourceFile(CompilerInstance & CI,const FrontendInputFile & Input)171f4a2713aSLionel Sambuc bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
172f4a2713aSLionel Sambuc const FrontendInputFile &Input) {
173f4a2713aSLionel Sambuc assert(!Instance && "Already processing a source file!");
174f4a2713aSLionel Sambuc assert(!Input.isEmpty() && "Unexpected empty filename!");
175f4a2713aSLionel Sambuc setCurrentInput(Input);
176f4a2713aSLionel Sambuc setCompilerInstance(&CI);
177f4a2713aSLionel Sambuc
178f4a2713aSLionel Sambuc StringRef InputFile = Input.getFile();
179f4a2713aSLionel Sambuc bool HasBegunSourceFile = false;
180f4a2713aSLionel Sambuc if (!BeginInvocation(CI))
181f4a2713aSLionel Sambuc goto failure;
182f4a2713aSLionel Sambuc
183f4a2713aSLionel Sambuc // AST files follow a very different path, since they share objects via the
184f4a2713aSLionel Sambuc // AST unit.
185f4a2713aSLionel Sambuc if (Input.getKind() == IK_AST) {
186f4a2713aSLionel Sambuc assert(!usesPreprocessorOnly() &&
187f4a2713aSLionel Sambuc "Attempt to pass AST file to preprocessor only action!");
188f4a2713aSLionel Sambuc assert(hasASTFileSupport() &&
189f4a2713aSLionel Sambuc "This action does not have AST file support!");
190f4a2713aSLionel Sambuc
191f4a2713aSLionel Sambuc IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
192*0a6a1f1dSLionel Sambuc
193*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTUnit> AST =
194*0a6a1f1dSLionel Sambuc ASTUnit::LoadFromASTFile(InputFile, Diags, CI.getFileSystemOpts());
195*0a6a1f1dSLionel Sambuc
196f4a2713aSLionel Sambuc if (!AST)
197f4a2713aSLionel Sambuc goto failure;
198f4a2713aSLionel Sambuc
199f4a2713aSLionel Sambuc // Inform the diagnostic client we are processing a source file.
200*0a6a1f1dSLionel Sambuc CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);
201f4a2713aSLionel Sambuc HasBegunSourceFile = true;
202f4a2713aSLionel Sambuc
203f4a2713aSLionel Sambuc // Set the shared objects, these are reset when we finish processing the
204f4a2713aSLionel Sambuc // file, otherwise the CompilerInstance will happily destroy them.
205f4a2713aSLionel Sambuc CI.setFileManager(&AST->getFileManager());
206f4a2713aSLionel Sambuc CI.setSourceManager(&AST->getSourceManager());
207f4a2713aSLionel Sambuc CI.setPreprocessor(&AST->getPreprocessor());
208f4a2713aSLionel Sambuc CI.setASTContext(&AST->getASTContext());
209f4a2713aSLionel Sambuc
210*0a6a1f1dSLionel Sambuc setCurrentInput(Input, std::move(AST));
211*0a6a1f1dSLionel Sambuc
212f4a2713aSLionel Sambuc // Initialize the action.
213f4a2713aSLionel Sambuc if (!BeginSourceFileAction(CI, InputFile))
214f4a2713aSLionel Sambuc goto failure;
215f4a2713aSLionel Sambuc
216f4a2713aSLionel Sambuc // Create the AST consumer.
217f4a2713aSLionel Sambuc CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile));
218f4a2713aSLionel Sambuc if (!CI.hasASTConsumer())
219f4a2713aSLionel Sambuc goto failure;
220f4a2713aSLionel Sambuc
221f4a2713aSLionel Sambuc return true;
222f4a2713aSLionel Sambuc }
223f4a2713aSLionel Sambuc
224*0a6a1f1dSLionel Sambuc if (!CI.hasVirtualFileSystem()) {
225*0a6a1f1dSLionel Sambuc if (IntrusiveRefCntPtr<vfs::FileSystem> VFS =
226*0a6a1f1dSLionel Sambuc createVFSFromCompilerInvocation(CI.getInvocation(),
227*0a6a1f1dSLionel Sambuc CI.getDiagnostics()))
228*0a6a1f1dSLionel Sambuc CI.setVirtualFileSystem(VFS);
229*0a6a1f1dSLionel Sambuc else
230*0a6a1f1dSLionel Sambuc goto failure;
231*0a6a1f1dSLionel Sambuc }
232*0a6a1f1dSLionel Sambuc
233f4a2713aSLionel Sambuc // Set up the file and source managers, if needed.
234f4a2713aSLionel Sambuc if (!CI.hasFileManager())
235f4a2713aSLionel Sambuc CI.createFileManager();
236f4a2713aSLionel Sambuc if (!CI.hasSourceManager())
237f4a2713aSLionel Sambuc CI.createSourceManager(CI.getFileManager());
238f4a2713aSLionel Sambuc
239f4a2713aSLionel Sambuc // IR files bypass the rest of initialization.
240f4a2713aSLionel Sambuc if (Input.getKind() == IK_LLVM_IR) {
241f4a2713aSLionel Sambuc assert(hasIRSupport() &&
242f4a2713aSLionel Sambuc "This action does not have IR file support!");
243f4a2713aSLionel Sambuc
244f4a2713aSLionel Sambuc // Inform the diagnostic client we are processing a source file.
245*0a6a1f1dSLionel Sambuc CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);
246f4a2713aSLionel Sambuc HasBegunSourceFile = true;
247f4a2713aSLionel Sambuc
248f4a2713aSLionel Sambuc // Initialize the action.
249f4a2713aSLionel Sambuc if (!BeginSourceFileAction(CI, InputFile))
250f4a2713aSLionel Sambuc goto failure;
251f4a2713aSLionel Sambuc
252*0a6a1f1dSLionel Sambuc // Initialize the main file entry.
253*0a6a1f1dSLionel Sambuc if (!CI.InitializeSourceManager(CurrentInput))
254*0a6a1f1dSLionel Sambuc goto failure;
255*0a6a1f1dSLionel Sambuc
256f4a2713aSLionel Sambuc return true;
257f4a2713aSLionel Sambuc }
258f4a2713aSLionel Sambuc
259f4a2713aSLionel Sambuc // If the implicit PCH include is actually a directory, rather than
260f4a2713aSLionel Sambuc // a single file, search for a suitable PCH file in that directory.
261f4a2713aSLionel Sambuc if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
262f4a2713aSLionel Sambuc FileManager &FileMgr = CI.getFileManager();
263f4a2713aSLionel Sambuc PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
264f4a2713aSLionel Sambuc StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
265f4a2713aSLionel Sambuc if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) {
266*0a6a1f1dSLionel Sambuc std::error_code EC;
267f4a2713aSLionel Sambuc SmallString<128> DirNative;
268f4a2713aSLionel Sambuc llvm::sys::path::native(PCHDir->getName(), DirNative);
269f4a2713aSLionel Sambuc bool Found = false;
270f4a2713aSLionel Sambuc for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd;
271f4a2713aSLionel Sambuc Dir != DirEnd && !EC; Dir.increment(EC)) {
272f4a2713aSLionel Sambuc // Check whether this is an acceptable AST file.
273f4a2713aSLionel Sambuc if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr,
274f4a2713aSLionel Sambuc CI.getLangOpts(),
275f4a2713aSLionel Sambuc CI.getTargetOpts(),
276f4a2713aSLionel Sambuc CI.getPreprocessorOpts())) {
277f4a2713aSLionel Sambuc PPOpts.ImplicitPCHInclude = Dir->path();
278f4a2713aSLionel Sambuc Found = true;
279f4a2713aSLionel Sambuc break;
280f4a2713aSLionel Sambuc }
281f4a2713aSLionel Sambuc }
282f4a2713aSLionel Sambuc
283f4a2713aSLionel Sambuc if (!Found) {
284f4a2713aSLionel Sambuc CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude;
285f4a2713aSLionel Sambuc return true;
286f4a2713aSLionel Sambuc }
287f4a2713aSLionel Sambuc }
288f4a2713aSLionel Sambuc }
289f4a2713aSLionel Sambuc
290*0a6a1f1dSLionel Sambuc // Set up the preprocessor if needed. When parsing model files the
291*0a6a1f1dSLionel Sambuc // preprocessor of the original source is reused.
292*0a6a1f1dSLionel Sambuc if (!isModelParsingAction())
293*0a6a1f1dSLionel Sambuc CI.createPreprocessor(getTranslationUnitKind());
294f4a2713aSLionel Sambuc
295f4a2713aSLionel Sambuc // Inform the diagnostic client we are processing a source file.
296f4a2713aSLionel Sambuc CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
297f4a2713aSLionel Sambuc &CI.getPreprocessor());
298f4a2713aSLionel Sambuc HasBegunSourceFile = true;
299f4a2713aSLionel Sambuc
300f4a2713aSLionel Sambuc // Initialize the action.
301f4a2713aSLionel Sambuc if (!BeginSourceFileAction(CI, InputFile))
302f4a2713aSLionel Sambuc goto failure;
303f4a2713aSLionel Sambuc
304*0a6a1f1dSLionel Sambuc // Initialize the main file entry. It is important that this occurs after
305*0a6a1f1dSLionel Sambuc // BeginSourceFileAction, which may change CurrentInput during module builds.
306*0a6a1f1dSLionel Sambuc if (!CI.InitializeSourceManager(CurrentInput))
307*0a6a1f1dSLionel Sambuc goto failure;
308*0a6a1f1dSLionel Sambuc
309f4a2713aSLionel Sambuc // Create the AST context and consumer unless this is a preprocessor only
310f4a2713aSLionel Sambuc // action.
311f4a2713aSLionel Sambuc if (!usesPreprocessorOnly()) {
312*0a6a1f1dSLionel Sambuc // Parsing a model file should reuse the existing ASTContext.
313*0a6a1f1dSLionel Sambuc if (!isModelParsingAction())
314f4a2713aSLionel Sambuc CI.createASTContext();
315f4a2713aSLionel Sambuc
316*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer> Consumer =
317*0a6a1f1dSLionel Sambuc CreateWrappedASTConsumer(CI, InputFile);
318f4a2713aSLionel Sambuc if (!Consumer)
319f4a2713aSLionel Sambuc goto failure;
320f4a2713aSLionel Sambuc
321*0a6a1f1dSLionel Sambuc // FIXME: should not overwrite ASTMutationListener when parsing model files?
322*0a6a1f1dSLionel Sambuc if (!isModelParsingAction())
323f4a2713aSLionel Sambuc CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());
324f4a2713aSLionel Sambuc
325f4a2713aSLionel Sambuc if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {
326f4a2713aSLionel Sambuc // Convert headers to PCH and chain them.
327*0a6a1f1dSLionel Sambuc IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader;
328*0a6a1f1dSLionel Sambuc source = createChainedIncludesSource(CI, FinalReader);
329f4a2713aSLionel Sambuc if (!source)
330f4a2713aSLionel Sambuc goto failure;
331*0a6a1f1dSLionel Sambuc CI.setModuleManager(static_cast<ASTReader *>(FinalReader.get()));
332f4a2713aSLionel Sambuc CI.getASTContext().setExternalSource(source);
333f4a2713aSLionel Sambuc } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
334f4a2713aSLionel Sambuc // Use PCH.
335f4a2713aSLionel Sambuc assert(hasPCHSupport() && "This action does not have PCH support!");
336f4a2713aSLionel Sambuc ASTDeserializationListener *DeserialListener =
337f4a2713aSLionel Sambuc Consumer->GetASTDeserializationListener();
338*0a6a1f1dSLionel Sambuc bool DeleteDeserialListener = false;
339*0a6a1f1dSLionel Sambuc if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) {
340*0a6a1f1dSLionel Sambuc DeserialListener = new DeserializedDeclsDumper(DeserialListener,
341*0a6a1f1dSLionel Sambuc DeleteDeserialListener);
342*0a6a1f1dSLionel Sambuc DeleteDeserialListener = true;
343*0a6a1f1dSLionel Sambuc }
344*0a6a1f1dSLionel Sambuc if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) {
345*0a6a1f1dSLionel Sambuc DeserialListener = new DeserializedDeclsChecker(
346*0a6a1f1dSLionel Sambuc CI.getASTContext(),
347f4a2713aSLionel Sambuc CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn,
348*0a6a1f1dSLionel Sambuc DeserialListener, DeleteDeserialListener);
349*0a6a1f1dSLionel Sambuc DeleteDeserialListener = true;
350*0a6a1f1dSLionel Sambuc }
351f4a2713aSLionel Sambuc CI.createPCHExternalASTSource(
352f4a2713aSLionel Sambuc CI.getPreprocessorOpts().ImplicitPCHInclude,
353f4a2713aSLionel Sambuc CI.getPreprocessorOpts().DisablePCHValidation,
354*0a6a1f1dSLionel Sambuc CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener,
355*0a6a1f1dSLionel Sambuc DeleteDeserialListener);
356f4a2713aSLionel Sambuc if (!CI.getASTContext().getExternalSource())
357f4a2713aSLionel Sambuc goto failure;
358f4a2713aSLionel Sambuc }
359f4a2713aSLionel Sambuc
360*0a6a1f1dSLionel Sambuc CI.setASTConsumer(std::move(Consumer));
361f4a2713aSLionel Sambuc if (!CI.hasASTConsumer())
362f4a2713aSLionel Sambuc goto failure;
363f4a2713aSLionel Sambuc }
364f4a2713aSLionel Sambuc
365f4a2713aSLionel Sambuc // Initialize built-in info as long as we aren't using an external AST
366f4a2713aSLionel Sambuc // source.
367f4a2713aSLionel Sambuc if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) {
368f4a2713aSLionel Sambuc Preprocessor &PP = CI.getPreprocessor();
369*0a6a1f1dSLionel Sambuc
370*0a6a1f1dSLionel Sambuc // If modules are enabled, create the module manager before creating
371*0a6a1f1dSLionel Sambuc // any builtins, so that all declarations know that they might be
372*0a6a1f1dSLionel Sambuc // extended by an external source.
373*0a6a1f1dSLionel Sambuc if (CI.getLangOpts().Modules)
374*0a6a1f1dSLionel Sambuc CI.createModuleManager();
375*0a6a1f1dSLionel Sambuc
376f4a2713aSLionel Sambuc PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
377f4a2713aSLionel Sambuc PP.getLangOpts());
378*0a6a1f1dSLionel Sambuc } else {
379*0a6a1f1dSLionel Sambuc // FIXME: If this is a problem, recover from it by creating a multiplex
380*0a6a1f1dSLionel Sambuc // source.
381*0a6a1f1dSLionel Sambuc assert((!CI.getLangOpts().Modules || CI.getModuleManager()) &&
382*0a6a1f1dSLionel Sambuc "modules enabled but created an external source that "
383*0a6a1f1dSLionel Sambuc "doesn't support modules");
384f4a2713aSLionel Sambuc }
385f4a2713aSLionel Sambuc
386*0a6a1f1dSLionel Sambuc // If we were asked to load any module files, do so now.
387*0a6a1f1dSLionel Sambuc for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles)
388*0a6a1f1dSLionel Sambuc if (!CI.loadModuleFile(ModuleFile))
389*0a6a1f1dSLionel Sambuc goto failure;
390*0a6a1f1dSLionel Sambuc
391f4a2713aSLionel Sambuc // If there is a layout overrides file, attach an external AST source that
392f4a2713aSLionel Sambuc // provides the layouts from that file.
393f4a2713aSLionel Sambuc if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() &&
394f4a2713aSLionel Sambuc CI.hasASTContext() && !CI.getASTContext().getExternalSource()) {
395*0a6a1f1dSLionel Sambuc IntrusiveRefCntPtr<ExternalASTSource>
396f4a2713aSLionel Sambuc Override(new LayoutOverrideSource(
397f4a2713aSLionel Sambuc CI.getFrontendOpts().OverrideRecordLayoutsFile));
398f4a2713aSLionel Sambuc CI.getASTContext().setExternalSource(Override);
399f4a2713aSLionel Sambuc }
400f4a2713aSLionel Sambuc
401f4a2713aSLionel Sambuc return true;
402f4a2713aSLionel Sambuc
403f4a2713aSLionel Sambuc // If we failed, reset state since the client will not end up calling the
404f4a2713aSLionel Sambuc // matching EndSourceFile().
405f4a2713aSLionel Sambuc failure:
406f4a2713aSLionel Sambuc if (isCurrentFileAST()) {
407*0a6a1f1dSLionel Sambuc CI.setASTContext(nullptr);
408*0a6a1f1dSLionel Sambuc CI.setPreprocessor(nullptr);
409*0a6a1f1dSLionel Sambuc CI.setSourceManager(nullptr);
410*0a6a1f1dSLionel Sambuc CI.setFileManager(nullptr);
411f4a2713aSLionel Sambuc }
412f4a2713aSLionel Sambuc
413f4a2713aSLionel Sambuc if (HasBegunSourceFile)
414f4a2713aSLionel Sambuc CI.getDiagnosticClient().EndSourceFile();
415f4a2713aSLionel Sambuc CI.clearOutputFiles(/*EraseFiles=*/true);
416f4a2713aSLionel Sambuc setCurrentInput(FrontendInputFile());
417*0a6a1f1dSLionel Sambuc setCompilerInstance(nullptr);
418f4a2713aSLionel Sambuc return false;
419f4a2713aSLionel Sambuc }
420f4a2713aSLionel Sambuc
Execute()421f4a2713aSLionel Sambuc bool FrontendAction::Execute() {
422f4a2713aSLionel Sambuc CompilerInstance &CI = getCompilerInstance();
423f4a2713aSLionel Sambuc
424f4a2713aSLionel Sambuc if (CI.hasFrontendTimer()) {
425f4a2713aSLionel Sambuc llvm::TimeRegion Timer(CI.getFrontendTimer());
426f4a2713aSLionel Sambuc ExecuteAction();
427f4a2713aSLionel Sambuc }
428f4a2713aSLionel Sambuc else ExecuteAction();
429f4a2713aSLionel Sambuc
430f4a2713aSLionel Sambuc // If we are supposed to rebuild the global module index, do so now unless
431f4a2713aSLionel Sambuc // there were any module-build failures.
432f4a2713aSLionel Sambuc if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() &&
433f4a2713aSLionel Sambuc CI.hasPreprocessor()) {
434f4a2713aSLionel Sambuc GlobalModuleIndex::writeIndex(
435f4a2713aSLionel Sambuc CI.getFileManager(),
436f4a2713aSLionel Sambuc CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
437f4a2713aSLionel Sambuc }
438f4a2713aSLionel Sambuc
439f4a2713aSLionel Sambuc return true;
440f4a2713aSLionel Sambuc }
441f4a2713aSLionel Sambuc
EndSourceFile()442f4a2713aSLionel Sambuc void FrontendAction::EndSourceFile() {
443f4a2713aSLionel Sambuc CompilerInstance &CI = getCompilerInstance();
444f4a2713aSLionel Sambuc
445f4a2713aSLionel Sambuc // Inform the diagnostic client we are done with this source file.
446f4a2713aSLionel Sambuc CI.getDiagnosticClient().EndSourceFile();
447f4a2713aSLionel Sambuc
448f4a2713aSLionel Sambuc // Inform the preprocessor we are done.
449f4a2713aSLionel Sambuc if (CI.hasPreprocessor())
450f4a2713aSLionel Sambuc CI.getPreprocessor().EndSourceFile();
451f4a2713aSLionel Sambuc
452*0a6a1f1dSLionel Sambuc // Finalize the action.
453*0a6a1f1dSLionel Sambuc EndSourceFileAction();
454*0a6a1f1dSLionel Sambuc
455*0a6a1f1dSLionel Sambuc // Sema references the ast consumer, so reset sema first.
456*0a6a1f1dSLionel Sambuc //
457*0a6a1f1dSLionel Sambuc // FIXME: There is more per-file stuff we could just drop here?
458*0a6a1f1dSLionel Sambuc bool DisableFree = CI.getFrontendOpts().DisableFree;
459*0a6a1f1dSLionel Sambuc if (DisableFree) {
460*0a6a1f1dSLionel Sambuc if (!isCurrentFileAST()) {
461*0a6a1f1dSLionel Sambuc CI.resetAndLeakSema();
462*0a6a1f1dSLionel Sambuc CI.resetAndLeakASTContext();
463*0a6a1f1dSLionel Sambuc }
464*0a6a1f1dSLionel Sambuc BuryPointer(CI.takeASTConsumer().get());
465*0a6a1f1dSLionel Sambuc } else {
466*0a6a1f1dSLionel Sambuc if (!isCurrentFileAST()) {
467*0a6a1f1dSLionel Sambuc CI.setSema(nullptr);
468*0a6a1f1dSLionel Sambuc CI.setASTContext(nullptr);
469*0a6a1f1dSLionel Sambuc }
470*0a6a1f1dSLionel Sambuc CI.setASTConsumer(nullptr);
471*0a6a1f1dSLionel Sambuc }
472*0a6a1f1dSLionel Sambuc
473f4a2713aSLionel Sambuc if (CI.getFrontendOpts().ShowStats) {
474f4a2713aSLionel Sambuc llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n";
475f4a2713aSLionel Sambuc CI.getPreprocessor().PrintStats();
476f4a2713aSLionel Sambuc CI.getPreprocessor().getIdentifierTable().PrintStats();
477f4a2713aSLionel Sambuc CI.getPreprocessor().getHeaderSearchInfo().PrintStats();
478f4a2713aSLionel Sambuc CI.getSourceManager().PrintStats();
479f4a2713aSLionel Sambuc llvm::errs() << "\n";
480f4a2713aSLionel Sambuc }
481f4a2713aSLionel Sambuc
482f4a2713aSLionel Sambuc // Cleanup the output streams, and erase the output files if instructed by the
483f4a2713aSLionel Sambuc // FrontendAction.
484f4a2713aSLionel Sambuc CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles());
485f4a2713aSLionel Sambuc
486*0a6a1f1dSLionel Sambuc // FIXME: Only do this if DisableFree is set.
487f4a2713aSLionel Sambuc if (isCurrentFileAST()) {
488*0a6a1f1dSLionel Sambuc CI.resetAndLeakSema();
489f4a2713aSLionel Sambuc CI.resetAndLeakASTContext();
490f4a2713aSLionel Sambuc CI.resetAndLeakPreprocessor();
491f4a2713aSLionel Sambuc CI.resetAndLeakSourceManager();
492f4a2713aSLionel Sambuc CI.resetAndLeakFileManager();
493f4a2713aSLionel Sambuc }
494f4a2713aSLionel Sambuc
495*0a6a1f1dSLionel Sambuc setCompilerInstance(nullptr);
496f4a2713aSLionel Sambuc setCurrentInput(FrontendInputFile());
497f4a2713aSLionel Sambuc }
498f4a2713aSLionel Sambuc
shouldEraseOutputFiles()499f4a2713aSLionel Sambuc bool FrontendAction::shouldEraseOutputFiles() {
500f4a2713aSLionel Sambuc return getCompilerInstance().getDiagnostics().hasErrorOccurred();
501f4a2713aSLionel Sambuc }
502f4a2713aSLionel Sambuc
503f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
504f4a2713aSLionel Sambuc // Utility Actions
505f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
506f4a2713aSLionel Sambuc
ExecuteAction()507f4a2713aSLionel Sambuc void ASTFrontendAction::ExecuteAction() {
508f4a2713aSLionel Sambuc CompilerInstance &CI = getCompilerInstance();
509f4a2713aSLionel Sambuc if (!CI.hasPreprocessor())
510f4a2713aSLionel Sambuc return;
511f4a2713aSLionel Sambuc
512f4a2713aSLionel Sambuc // FIXME: Move the truncation aspect of this into Sema, we delayed this till
513f4a2713aSLionel Sambuc // here so the source manager would be initialized.
514f4a2713aSLionel Sambuc if (hasCodeCompletionSupport() &&
515f4a2713aSLionel Sambuc !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
516f4a2713aSLionel Sambuc CI.createCodeCompletionConsumer();
517f4a2713aSLionel Sambuc
518f4a2713aSLionel Sambuc // Use a code completion consumer?
519*0a6a1f1dSLionel Sambuc CodeCompleteConsumer *CompletionConsumer = nullptr;
520f4a2713aSLionel Sambuc if (CI.hasCodeCompletionConsumer())
521f4a2713aSLionel Sambuc CompletionConsumer = &CI.getCodeCompletionConsumer();
522f4a2713aSLionel Sambuc
523f4a2713aSLionel Sambuc if (!CI.hasSema())
524f4a2713aSLionel Sambuc CI.createSema(getTranslationUnitKind(), CompletionConsumer);
525f4a2713aSLionel Sambuc
526f4a2713aSLionel Sambuc ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats,
527f4a2713aSLionel Sambuc CI.getFrontendOpts().SkipFunctionBodies);
528f4a2713aSLionel Sambuc }
529f4a2713aSLionel Sambuc
anchor()530f4a2713aSLionel Sambuc void PluginASTAction::anchor() { }
531f4a2713aSLionel Sambuc
532*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)533f4a2713aSLionel Sambuc PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
534f4a2713aSLionel Sambuc StringRef InFile) {
535f4a2713aSLionel Sambuc llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
536f4a2713aSLionel Sambuc }
537f4a2713aSLionel Sambuc
538*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)539*0a6a1f1dSLionel Sambuc WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI,
540f4a2713aSLionel Sambuc StringRef InFile) {
541f4a2713aSLionel Sambuc return WrappedAction->CreateASTConsumer(CI, InFile);
542f4a2713aSLionel Sambuc }
BeginInvocation(CompilerInstance & CI)543f4a2713aSLionel Sambuc bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) {
544f4a2713aSLionel Sambuc return WrappedAction->BeginInvocation(CI);
545f4a2713aSLionel Sambuc }
BeginSourceFileAction(CompilerInstance & CI,StringRef Filename)546f4a2713aSLionel Sambuc bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI,
547f4a2713aSLionel Sambuc StringRef Filename) {
548f4a2713aSLionel Sambuc WrappedAction->setCurrentInput(getCurrentInput());
549f4a2713aSLionel Sambuc WrappedAction->setCompilerInstance(&CI);
550f4a2713aSLionel Sambuc return WrappedAction->BeginSourceFileAction(CI, Filename);
551f4a2713aSLionel Sambuc }
ExecuteAction()552f4a2713aSLionel Sambuc void WrapperFrontendAction::ExecuteAction() {
553f4a2713aSLionel Sambuc WrappedAction->ExecuteAction();
554f4a2713aSLionel Sambuc }
EndSourceFileAction()555f4a2713aSLionel Sambuc void WrapperFrontendAction::EndSourceFileAction() {
556f4a2713aSLionel Sambuc WrappedAction->EndSourceFileAction();
557f4a2713aSLionel Sambuc }
558f4a2713aSLionel Sambuc
usesPreprocessorOnly() const559f4a2713aSLionel Sambuc bool WrapperFrontendAction::usesPreprocessorOnly() const {
560f4a2713aSLionel Sambuc return WrappedAction->usesPreprocessorOnly();
561f4a2713aSLionel Sambuc }
getTranslationUnitKind()562f4a2713aSLionel Sambuc TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() {
563f4a2713aSLionel Sambuc return WrappedAction->getTranslationUnitKind();
564f4a2713aSLionel Sambuc }
hasPCHSupport() const565f4a2713aSLionel Sambuc bool WrapperFrontendAction::hasPCHSupport() const {
566f4a2713aSLionel Sambuc return WrappedAction->hasPCHSupport();
567f4a2713aSLionel Sambuc }
hasASTFileSupport() const568f4a2713aSLionel Sambuc bool WrapperFrontendAction::hasASTFileSupport() const {
569f4a2713aSLionel Sambuc return WrappedAction->hasASTFileSupport();
570f4a2713aSLionel Sambuc }
hasIRSupport() const571f4a2713aSLionel Sambuc bool WrapperFrontendAction::hasIRSupport() const {
572f4a2713aSLionel Sambuc return WrappedAction->hasIRSupport();
573f4a2713aSLionel Sambuc }
hasCodeCompletionSupport() const574f4a2713aSLionel Sambuc bool WrapperFrontendAction::hasCodeCompletionSupport() const {
575f4a2713aSLionel Sambuc return WrappedAction->hasCodeCompletionSupport();
576f4a2713aSLionel Sambuc }
577f4a2713aSLionel Sambuc
WrapperFrontendAction(FrontendAction * WrappedAction)578f4a2713aSLionel Sambuc WrapperFrontendAction::WrapperFrontendAction(FrontendAction *WrappedAction)
579f4a2713aSLionel Sambuc : WrappedAction(WrappedAction) {}
580f4a2713aSLionel Sambuc
581