File: | clang/lib/Frontend/FrontendAction.cpp |
Warning: | line 895, column 5 Potential leak of memory pointed to by 'DeserialListener' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- FrontendAction.cpp -----------------------------------------------===// | ||||
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 "clang/Frontend/FrontendAction.h" | ||||
10 | #include "clang/AST/ASTConsumer.h" | ||||
11 | #include "clang/AST/ASTContext.h" | ||||
12 | #include "clang/AST/DeclGroup.h" | ||||
13 | #include "clang/Basic/Builtins.h" | ||||
14 | #include "clang/Basic/LangStandard.h" | ||||
15 | #include "clang/Frontend/ASTUnit.h" | ||||
16 | #include "clang/Frontend/CompilerInstance.h" | ||||
17 | #include "clang/Frontend/FrontendDiagnostic.h" | ||||
18 | #include "clang/Frontend/FrontendPluginRegistry.h" | ||||
19 | #include "clang/Frontend/LayoutOverrideSource.h" | ||||
20 | #include "clang/Frontend/MultiplexConsumer.h" | ||||
21 | #include "clang/Frontend/Utils.h" | ||||
22 | #include "clang/Lex/HeaderSearch.h" | ||||
23 | #include "clang/Lex/LiteralSupport.h" | ||||
24 | #include "clang/Lex/Preprocessor.h" | ||||
25 | #include "clang/Lex/PreprocessorOptions.h" | ||||
26 | #include "clang/Parse/ParseAST.h" | ||||
27 | #include "clang/Serialization/ASTDeserializationListener.h" | ||||
28 | #include "clang/Serialization/ASTReader.h" | ||||
29 | #include "clang/Serialization/GlobalModuleIndex.h" | ||||
30 | #include "llvm/Support/BuryPointer.h" | ||||
31 | #include "llvm/Support/ErrorHandling.h" | ||||
32 | #include "llvm/Support/FileSystem.h" | ||||
33 | #include "llvm/Support/Path.h" | ||||
34 | #include "llvm/Support/Timer.h" | ||||
35 | #include "llvm/Support/raw_ostream.h" | ||||
36 | #include <system_error> | ||||
37 | using namespace clang; | ||||
38 | |||||
39 | LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry)namespace llvm { template<typename T> typename Registry <T>::node *Registry<T>::Head = nullptr; template< typename T> typename Registry<T>::node *Registry< T>::Tail = nullptr; template<typename T> void Registry <T>::add_node(typename Registry<T>::node *N) { if (Tail) Tail->Next = N; else Head = N; Tail = N; } template <typename T> typename Registry<T>::iterator Registry <T>::begin() { return iterator(Head); } template FrontendPluginRegistry ::node *Registry<FrontendPluginRegistry::type>::Head; template FrontendPluginRegistry::node *Registry<FrontendPluginRegistry ::type>::Tail; template void Registry<FrontendPluginRegistry ::type>::add_node(FrontendPluginRegistry::node*); template FrontendPluginRegistry::iterator Registry<FrontendPluginRegistry ::type>::begin(); } | ||||
40 | |||||
41 | namespace { | ||||
42 | |||||
43 | class DelegatingDeserializationListener : public ASTDeserializationListener { | ||||
44 | ASTDeserializationListener *Previous; | ||||
45 | bool DeletePrevious; | ||||
46 | |||||
47 | public: | ||||
48 | explicit DelegatingDeserializationListener( | ||||
49 | ASTDeserializationListener *Previous, bool DeletePrevious) | ||||
50 | : Previous(Previous), DeletePrevious(DeletePrevious) {} | ||||
51 | ~DelegatingDeserializationListener() override { | ||||
52 | if (DeletePrevious) | ||||
53 | delete Previous; | ||||
54 | } | ||||
55 | |||||
56 | void ReaderInitialized(ASTReader *Reader) override { | ||||
57 | if (Previous) | ||||
58 | Previous->ReaderInitialized(Reader); | ||||
59 | } | ||||
60 | void IdentifierRead(serialization::IdentID ID, | ||||
61 | IdentifierInfo *II) override { | ||||
62 | if (Previous) | ||||
63 | Previous->IdentifierRead(ID, II); | ||||
64 | } | ||||
65 | void TypeRead(serialization::TypeIdx Idx, QualType T) override { | ||||
66 | if (Previous) | ||||
67 | Previous->TypeRead(Idx, T); | ||||
68 | } | ||||
69 | void DeclRead(serialization::DeclID ID, const Decl *D) override { | ||||
70 | if (Previous) | ||||
71 | Previous->DeclRead(ID, D); | ||||
72 | } | ||||
73 | void SelectorRead(serialization::SelectorID ID, Selector Sel) override { | ||||
74 | if (Previous) | ||||
75 | Previous->SelectorRead(ID, Sel); | ||||
76 | } | ||||
77 | void MacroDefinitionRead(serialization::PreprocessedEntityID PPID, | ||||
78 | MacroDefinitionRecord *MD) override { | ||||
79 | if (Previous) | ||||
80 | Previous->MacroDefinitionRead(PPID, MD); | ||||
81 | } | ||||
82 | }; | ||||
83 | |||||
84 | /// Dumps deserialized declarations. | ||||
85 | class DeserializedDeclsDumper : public DelegatingDeserializationListener { | ||||
86 | public: | ||||
87 | explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous, | ||||
88 | bool DeletePrevious) | ||||
89 | : DelegatingDeserializationListener(Previous, DeletePrevious) {} | ||||
90 | |||||
91 | void DeclRead(serialization::DeclID ID, const Decl *D) override { | ||||
92 | llvm::outs() << "PCH DECL: " << D->getDeclKindName(); | ||||
93 | if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { | ||||
94 | llvm::outs() << " - "; | ||||
95 | ND->printQualifiedName(llvm::outs()); | ||||
96 | } | ||||
97 | llvm::outs() << "\n"; | ||||
98 | |||||
99 | DelegatingDeserializationListener::DeclRead(ID, D); | ||||
100 | } | ||||
101 | }; | ||||
102 | |||||
103 | /// Checks deserialized declarations and emits error if a name | ||||
104 | /// matches one given in command-line using -error-on-deserialized-decl. | ||||
105 | class DeserializedDeclsChecker : public DelegatingDeserializationListener { | ||||
106 | ASTContext &Ctx; | ||||
107 | std::set<std::string> NamesToCheck; | ||||
108 | |||||
109 | public: | ||||
110 | DeserializedDeclsChecker(ASTContext &Ctx, | ||||
111 | const std::set<std::string> &NamesToCheck, | ||||
112 | ASTDeserializationListener *Previous, | ||||
113 | bool DeletePrevious) | ||||
114 | : DelegatingDeserializationListener(Previous, DeletePrevious), Ctx(Ctx), | ||||
115 | NamesToCheck(NamesToCheck) {} | ||||
116 | |||||
117 | void DeclRead(serialization::DeclID ID, const Decl *D) override { | ||||
118 | if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) | ||||
119 | if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) { | ||||
120 | unsigned DiagID | ||||
121 | = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, | ||||
122 | "%0 was deserialized"); | ||||
123 | Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID) | ||||
124 | << ND; | ||||
125 | } | ||||
126 | |||||
127 | DelegatingDeserializationListener::DeclRead(ID, D); | ||||
128 | } | ||||
129 | }; | ||||
130 | |||||
131 | } // end anonymous namespace | ||||
132 | |||||
133 | FrontendAction::FrontendAction() : Instance(nullptr) {} | ||||
134 | |||||
135 | FrontendAction::~FrontendAction() {} | ||||
136 | |||||
137 | void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput, | ||||
138 | std::unique_ptr<ASTUnit> AST) { | ||||
139 | this->CurrentInput = CurrentInput; | ||||
140 | CurrentASTUnit = std::move(AST); | ||||
141 | } | ||||
142 | |||||
143 | Module *FrontendAction::getCurrentModule() const { | ||||
144 | CompilerInstance &CI = getCompilerInstance(); | ||||
145 | return CI.getPreprocessor().getHeaderSearchInfo().lookupModule( | ||||
146 | CI.getLangOpts().CurrentModule, /*AllowSearch*/false); | ||||
147 | } | ||||
148 | |||||
149 | std::unique_ptr<ASTConsumer> | ||||
150 | FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, | ||||
151 | StringRef InFile) { | ||||
152 | std::unique_ptr<ASTConsumer> Consumer = CreateASTConsumer(CI, InFile); | ||||
153 | if (!Consumer) | ||||
154 | return nullptr; | ||||
155 | |||||
156 | // Validate -add-plugin args. | ||||
157 | bool FoundAllPlugins = true; | ||||
158 | for (const std::string &Arg : CI.getFrontendOpts().AddPluginActions) { | ||||
159 | bool Found = false; | ||||
160 | for (const FrontendPluginRegistry::entry &Plugin : | ||||
161 | FrontendPluginRegistry::entries()) { | ||||
162 | if (Plugin.getName() == Arg) | ||||
163 | Found = true; | ||||
164 | } | ||||
165 | if (!Found) { | ||||
166 | CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) << Arg; | ||||
167 | FoundAllPlugins = false; | ||||
168 | } | ||||
169 | } | ||||
170 | if (!FoundAllPlugins) | ||||
171 | return nullptr; | ||||
172 | |||||
173 | // If there are no registered plugins we don't need to wrap the consumer | ||||
174 | if (FrontendPluginRegistry::begin() == FrontendPluginRegistry::end()) | ||||
175 | return Consumer; | ||||
176 | |||||
177 | // If this is a code completion run, avoid invoking the plugin consumers | ||||
178 | if (CI.hasCodeCompletionConsumer()) | ||||
179 | return Consumer; | ||||
180 | |||||
181 | // Collect the list of plugins that go before the main action (in Consumers) | ||||
182 | // or after it (in AfterConsumers) | ||||
183 | std::vector<std::unique_ptr<ASTConsumer>> Consumers; | ||||
184 | std::vector<std::unique_ptr<ASTConsumer>> AfterConsumers; | ||||
185 | for (const FrontendPluginRegistry::entry &Plugin : | ||||
186 | FrontendPluginRegistry::entries()) { | ||||
187 | std::unique_ptr<PluginASTAction> P = Plugin.instantiate(); | ||||
188 | PluginASTAction::ActionType ActionType = P->getActionType(); | ||||
189 | if (ActionType == PluginASTAction::Cmdline) { | ||||
190 | // This is O(|plugins| * |add_plugins|), but since both numbers are | ||||
191 | // way below 50 in practice, that's ok. | ||||
192 | if (llvm::any_of(CI.getFrontendOpts().AddPluginActions, | ||||
193 | [&](const std::string &PluginAction) { | ||||
194 | return PluginAction == Plugin.getName(); | ||||
195 | })) | ||||
196 | ActionType = PluginASTAction::AddAfterMainAction; | ||||
197 | } | ||||
198 | if ((ActionType == PluginASTAction::AddBeforeMainAction || | ||||
199 | ActionType == PluginASTAction::AddAfterMainAction) && | ||||
200 | P->ParseArgs( | ||||
201 | CI, | ||||
202 | CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())])) { | ||||
203 | std::unique_ptr<ASTConsumer> PluginConsumer = P->CreateASTConsumer(CI, InFile); | ||||
204 | if (ActionType == PluginASTAction::AddBeforeMainAction) { | ||||
205 | Consumers.push_back(std::move(PluginConsumer)); | ||||
206 | } else { | ||||
207 | AfterConsumers.push_back(std::move(PluginConsumer)); | ||||
208 | } | ||||
209 | } | ||||
210 | } | ||||
211 | |||||
212 | // Add to Consumers the main consumer, then all the plugins that go after it | ||||
213 | Consumers.push_back(std::move(Consumer)); | ||||
214 | for (auto &C : AfterConsumers) { | ||||
215 | Consumers.push_back(std::move(C)); | ||||
216 | } | ||||
217 | |||||
218 | return std::make_unique<MultiplexConsumer>(std::move(Consumers)); | ||||
219 | } | ||||
220 | |||||
221 | /// For preprocessed files, if the first line is the linemarker and specifies | ||||
222 | /// the original source file name, use that name as the input file name. | ||||
223 | /// Returns the location of the first token after the line marker directive. | ||||
224 | /// | ||||
225 | /// \param CI The compiler instance. | ||||
226 | /// \param InputFile Populated with the filename from the line marker. | ||||
227 | /// \param IsModuleMap If \c true, add a line note corresponding to this line | ||||
228 | /// directive. (We need to do this because the directive will not be | ||||
229 | /// visited by the preprocessor.) | ||||
230 | static SourceLocation ReadOriginalFileName(CompilerInstance &CI, | ||||
231 | std::string &InputFile, | ||||
232 | bool IsModuleMap = false) { | ||||
233 | auto &SourceMgr = CI.getSourceManager(); | ||||
234 | auto MainFileID = SourceMgr.getMainFileID(); | ||||
235 | |||||
236 | auto MainFileBuf = SourceMgr.getBufferOrNone(MainFileID); | ||||
237 | if (!MainFileBuf) | ||||
238 | return SourceLocation(); | ||||
239 | |||||
240 | std::unique_ptr<Lexer> RawLexer( | ||||
241 | new Lexer(MainFileID, *MainFileBuf, SourceMgr, CI.getLangOpts())); | ||||
242 | |||||
243 | // If the first line has the syntax of | ||||
244 | // | ||||
245 | // # NUM "FILENAME" | ||||
246 | // | ||||
247 | // we use FILENAME as the input file name. | ||||
248 | Token T; | ||||
249 | if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash) | ||||
250 | return SourceLocation(); | ||||
251 | if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() || | ||||
252 | T.getKind() != tok::numeric_constant) | ||||
253 | return SourceLocation(); | ||||
254 | |||||
255 | unsigned LineNo; | ||||
256 | SourceLocation LineNoLoc = T.getLocation(); | ||||
257 | if (IsModuleMap) { | ||||
258 | llvm::SmallString<16> Buffer; | ||||
259 | if (Lexer::getSpelling(LineNoLoc, Buffer, SourceMgr, CI.getLangOpts()) | ||||
260 | .getAsInteger(10, LineNo)) | ||||
261 | return SourceLocation(); | ||||
262 | } | ||||
263 | |||||
264 | RawLexer->LexFromRawLexer(T); | ||||
265 | if (T.isAtStartOfLine() || T.getKind() != tok::string_literal) | ||||
266 | return SourceLocation(); | ||||
267 | |||||
268 | StringLiteralParser Literal(T, CI.getPreprocessor()); | ||||
269 | if (Literal.hadError) | ||||
270 | return SourceLocation(); | ||||
271 | RawLexer->LexFromRawLexer(T); | ||||
272 | if (T.isNot(tok::eof) && !T.isAtStartOfLine()) | ||||
273 | return SourceLocation(); | ||||
274 | InputFile = Literal.GetString().str(); | ||||
275 | |||||
276 | if (IsModuleMap) | ||||
277 | CI.getSourceManager().AddLineNote( | ||||
278 | LineNoLoc, LineNo, SourceMgr.getLineTableFilenameID(InputFile), false, | ||||
279 | false, SrcMgr::C_User_ModuleMap); | ||||
280 | |||||
281 | return T.getLocation(); | ||||
282 | } | ||||
283 | |||||
284 | static SmallVectorImpl<char> & | ||||
285 | operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) { | ||||
286 | Includes.append(RHS.begin(), RHS.end()); | ||||
287 | return Includes; | ||||
288 | } | ||||
289 | |||||
290 | static void addHeaderInclude(StringRef HeaderName, | ||||
291 | SmallVectorImpl<char> &Includes, | ||||
292 | const LangOptions &LangOpts, | ||||
293 | bool IsExternC) { | ||||
294 | if (IsExternC && LangOpts.CPlusPlus) | ||||
295 | Includes += "extern \"C\" {\n"; | ||||
296 | if (LangOpts.ObjC) | ||||
297 | Includes += "#import \""; | ||||
298 | else | ||||
299 | Includes += "#include \""; | ||||
300 | |||||
301 | Includes += HeaderName; | ||||
302 | |||||
303 | Includes += "\"\n"; | ||||
304 | if (IsExternC && LangOpts.CPlusPlus) | ||||
305 | Includes += "}\n"; | ||||
306 | } | ||||
307 | |||||
308 | /// Collect the set of header includes needed to construct the given | ||||
309 | /// module and update the TopHeaders file set of the module. | ||||
310 | /// | ||||
311 | /// \param Module The module we're collecting includes from. | ||||
312 | /// | ||||
313 | /// \param Includes Will be augmented with the set of \#includes or \#imports | ||||
314 | /// needed to load all of the named headers. | ||||
315 | static std::error_code collectModuleHeaderIncludes( | ||||
316 | const LangOptions &LangOpts, FileManager &FileMgr, DiagnosticsEngine &Diag, | ||||
317 | ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl<char> &Includes) { | ||||
318 | // Don't collect any headers for unavailable modules. | ||||
319 | if (!Module->isAvailable()) | ||||
320 | return std::error_code(); | ||||
321 | |||||
322 | // Resolve all lazy header directives to header files. | ||||
323 | ModMap.resolveHeaderDirectives(Module); | ||||
324 | |||||
325 | // If any headers are missing, we can't build this module. In most cases, | ||||
326 | // diagnostics for this should have already been produced; we only get here | ||||
327 | // if explicit stat information was provided. | ||||
328 | // FIXME: If the name resolves to a file with different stat information, | ||||
329 | // produce a better diagnostic. | ||||
330 | if (!Module->MissingHeaders.empty()) { | ||||
331 | auto &MissingHeader = Module->MissingHeaders.front(); | ||||
332 | Diag.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing) | ||||
333 | << MissingHeader.IsUmbrella << MissingHeader.FileName; | ||||
334 | return std::error_code(); | ||||
335 | } | ||||
336 | |||||
337 | // Add includes for each of these headers. | ||||
338 | for (auto HK : {Module::HK_Normal, Module::HK_Private}) { | ||||
339 | for (Module::Header &H : Module->Headers[HK]) { | ||||
340 | Module->addTopHeader(H.Entry); | ||||
341 | // Use the path as specified in the module map file. We'll look for this | ||||
342 | // file relative to the module build directory (the directory containing | ||||
343 | // the module map file) so this will find the same file that we found | ||||
344 | // while parsing the module map. | ||||
345 | addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts, | ||||
346 | Module->IsExternC); | ||||
347 | } | ||||
348 | } | ||||
349 | // Note that Module->PrivateHeaders will not be a TopHeader. | ||||
350 | |||||
351 | if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) { | ||||
352 | Module->addTopHeader(UmbrellaHeader.Entry); | ||||
353 | if (Module->Parent) | ||||
354 | // Include the umbrella header for submodules. | ||||
355 | addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory, | ||||
356 | Includes, LangOpts, Module->IsExternC); | ||||
357 | } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) { | ||||
358 | // Add all of the headers we find in this subdirectory. | ||||
359 | std::error_code EC; | ||||
360 | SmallString<128> DirNative; | ||||
361 | llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative); | ||||
362 | |||||
363 | llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); | ||||
364 | SmallVector<std::pair<std::string, const FileEntry *>, 8> Headers; | ||||
365 | for (llvm::vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End; | ||||
366 | Dir != End && !EC; Dir.increment(EC)) { | ||||
367 | // Check whether this entry has an extension typically associated with | ||||
368 | // headers. | ||||
369 | if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path())) | ||||
370 | .Cases(".h", ".H", ".hh", ".hpp", true) | ||||
371 | .Default(false)) | ||||
372 | continue; | ||||
373 | |||||
374 | auto Header = FileMgr.getFile(Dir->path()); | ||||
375 | // FIXME: This shouldn't happen unless there is a file system race. Is | ||||
376 | // that worth diagnosing? | ||||
377 | if (!Header) | ||||
378 | continue; | ||||
379 | |||||
380 | // If this header is marked 'unavailable' in this module, don't include | ||||
381 | // it. | ||||
382 | if (ModMap.isHeaderUnavailableInModule(*Header, Module)) | ||||
383 | continue; | ||||
384 | |||||
385 | // Compute the relative path from the directory to this file. | ||||
386 | SmallVector<StringRef, 16> Components; | ||||
387 | auto PathIt = llvm::sys::path::rbegin(Dir->path()); | ||||
388 | for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt) | ||||
389 | Components.push_back(*PathIt); | ||||
390 | SmallString<128> RelativeHeader( | ||||
391 | UmbrellaDir.PathRelativeToRootModuleDirectory); | ||||
392 | for (auto It = Components.rbegin(), End = Components.rend(); It != End; | ||||
393 | ++It) | ||||
394 | llvm::sys::path::append(RelativeHeader, *It); | ||||
395 | |||||
396 | std::string RelName = RelativeHeader.c_str(); | ||||
397 | Headers.push_back(std::make_pair(RelName, *Header)); | ||||
398 | } | ||||
399 | |||||
400 | if (EC) | ||||
401 | return EC; | ||||
402 | |||||
403 | // Sort header paths and make the header inclusion order deterministic | ||||
404 | // across different OSs and filesystems. | ||||
405 | llvm::sort(Headers.begin(), Headers.end(), []( | ||||
406 | const std::pair<std::string, const FileEntry *> &LHS, | ||||
407 | const std::pair<std::string, const FileEntry *> &RHS) { | ||||
408 | return LHS.first < RHS.first; | ||||
409 | }); | ||||
410 | for (auto &H : Headers) { | ||||
411 | // Include this header as part of the umbrella directory. | ||||
412 | Module->addTopHeader(H.second); | ||||
413 | addHeaderInclude(H.first, Includes, LangOpts, Module->IsExternC); | ||||
414 | } | ||||
415 | } | ||||
416 | |||||
417 | // Recurse into submodules. | ||||
418 | for (clang::Module::submodule_iterator Sub = Module->submodule_begin(), | ||||
419 | SubEnd = Module->submodule_end(); | ||||
420 | Sub != SubEnd; ++Sub) | ||||
421 | if (std::error_code Err = collectModuleHeaderIncludes( | ||||
422 | LangOpts, FileMgr, Diag, ModMap, *Sub, Includes)) | ||||
423 | return Err; | ||||
424 | |||||
425 | return std::error_code(); | ||||
426 | } | ||||
427 | |||||
428 | static bool loadModuleMapForModuleBuild(CompilerInstance &CI, bool IsSystem, | ||||
429 | bool IsPreprocessed, | ||||
430 | std::string &PresumedModuleMapFile, | ||||
431 | unsigned &Offset) { | ||||
432 | auto &SrcMgr = CI.getSourceManager(); | ||||
433 | HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); | ||||
434 | |||||
435 | // Map the current input to a file. | ||||
436 | FileID ModuleMapID = SrcMgr.getMainFileID(); | ||||
437 | const FileEntry *ModuleMap = SrcMgr.getFileEntryForID(ModuleMapID); | ||||
438 | |||||
439 | // If the module map is preprocessed, handle the initial line marker; | ||||
440 | // line directives are not part of the module map syntax in general. | ||||
441 | Offset = 0; | ||||
442 | if (IsPreprocessed) { | ||||
443 | SourceLocation EndOfLineMarker = | ||||
444 | ReadOriginalFileName(CI, PresumedModuleMapFile, /*IsModuleMap*/ true); | ||||
445 | if (EndOfLineMarker.isValid()) | ||||
446 | Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second; | ||||
447 | } | ||||
448 | |||||
449 | // Load the module map file. | ||||
450 | if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset, | ||||
451 | PresumedModuleMapFile)) | ||||
452 | return true; | ||||
453 | |||||
454 | if (SrcMgr.getBufferOrFake(ModuleMapID).getBufferSize() == Offset) | ||||
455 | Offset = 0; | ||||
456 | |||||
457 | return false; | ||||
458 | } | ||||
459 | |||||
460 | static Module *prepareToBuildModule(CompilerInstance &CI, | ||||
461 | StringRef ModuleMapFilename) { | ||||
462 | if (CI.getLangOpts().CurrentModule.empty()) { | ||||
463 | CI.getDiagnostics().Report(diag::err_missing_module_name); | ||||
464 | |||||
465 | // FIXME: Eventually, we could consider asking whether there was just | ||||
466 | // a single module described in the module map, and use that as a | ||||
467 | // default. Then it would be fairly trivial to just "compile" a module | ||||
468 | // map with a single module (the common case). | ||||
469 | return nullptr; | ||||
470 | } | ||||
471 | |||||
472 | // Dig out the module definition. | ||||
473 | HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); | ||||
474 | Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, | ||||
475 | /*AllowSearch=*/true); | ||||
476 | if (!M) { | ||||
477 | CI.getDiagnostics().Report(diag::err_missing_module) | ||||
478 | << CI.getLangOpts().CurrentModule << ModuleMapFilename; | ||||
479 | |||||
480 | return nullptr; | ||||
481 | } | ||||
482 | |||||
483 | // Check whether we can build this module at all. | ||||
484 | if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(), | ||||
485 | CI.getDiagnostics(), M)) | ||||
486 | return nullptr; | ||||
487 | |||||
488 | // Inform the preprocessor that includes from within the input buffer should | ||||
489 | // be resolved relative to the build directory of the module map file. | ||||
490 | CI.getPreprocessor().setMainFileDir(M->Directory); | ||||
491 | |||||
492 | // If the module was inferred from a different module map (via an expanded | ||||
493 | // umbrella module definition), track that fact. | ||||
494 | // FIXME: It would be preferable to fill this in as part of processing | ||||
495 | // the module map, rather than adding it after the fact. | ||||
496 | StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap; | ||||
497 | if (!OriginalModuleMapName.empty()) { | ||||
498 | auto OriginalModuleMap = | ||||
499 | CI.getFileManager().getFile(OriginalModuleMapName, | ||||
500 | /*openFile*/ true); | ||||
501 | if (!OriginalModuleMap) { | ||||
502 | CI.getDiagnostics().Report(diag::err_module_map_not_found) | ||||
503 | << OriginalModuleMapName; | ||||
504 | return nullptr; | ||||
505 | } | ||||
506 | if (*OriginalModuleMap != CI.getSourceManager().getFileEntryForID( | ||||
507 | CI.getSourceManager().getMainFileID())) { | ||||
508 | M->IsInferred = true; | ||||
509 | CI.getPreprocessor().getHeaderSearchInfo().getModuleMap() | ||||
510 | .setInferredModuleAllowedBy(M, *OriginalModuleMap); | ||||
511 | } | ||||
512 | } | ||||
513 | |||||
514 | // If we're being run from the command-line, the module build stack will not | ||||
515 | // have been filled in yet, so complete it now in order to allow us to detect | ||||
516 | // module cycles. | ||||
517 | SourceManager &SourceMgr = CI.getSourceManager(); | ||||
518 | if (SourceMgr.getModuleBuildStack().empty()) | ||||
519 | SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule, | ||||
520 | FullSourceLoc(SourceLocation(), SourceMgr)); | ||||
521 | return M; | ||||
522 | } | ||||
523 | |||||
524 | /// Compute the input buffer that should be used to build the specified module. | ||||
525 | static std::unique_ptr<llvm::MemoryBuffer> | ||||
526 | getInputBufferForModule(CompilerInstance &CI, Module *M) { | ||||
527 | FileManager &FileMgr = CI.getFileManager(); | ||||
528 | |||||
529 | // Collect the set of #includes we need to build the module. | ||||
530 | SmallString<256> HeaderContents; | ||||
531 | std::error_code Err = std::error_code(); | ||||
532 | if (Module::Header UmbrellaHeader = M->getUmbrellaHeader()) | ||||
533 | addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory, | ||||
534 | HeaderContents, CI.getLangOpts(), M->IsExternC); | ||||
535 | Err = collectModuleHeaderIncludes( | ||||
536 | CI.getLangOpts(), FileMgr, CI.getDiagnostics(), | ||||
537 | CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M, | ||||
538 | HeaderContents); | ||||
539 | |||||
540 | if (Err) { | ||||
541 | CI.getDiagnostics().Report(diag::err_module_cannot_create_includes) | ||||
542 | << M->getFullModuleName() << Err.message(); | ||||
543 | return nullptr; | ||||
544 | } | ||||
545 | |||||
546 | return llvm::MemoryBuffer::getMemBufferCopy( | ||||
547 | HeaderContents, Module::getModuleInputBufferName()); | ||||
548 | } | ||||
549 | |||||
550 | bool FrontendAction::BeginSourceFile(CompilerInstance &CI, | ||||
551 | const FrontendInputFile &RealInput) { | ||||
552 | FrontendInputFile Input(RealInput); | ||||
553 | assert(!Instance && "Already processing a source file!")(static_cast <bool> (!Instance && "Already processing a source file!" ) ? void (0) : __assert_fail ("!Instance && \"Already processing a source file!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 553, __extension__ __PRETTY_FUNCTION__)); | ||||
| |||||
554 | assert(!Input.isEmpty() && "Unexpected empty filename!")(static_cast <bool> (!Input.isEmpty() && "Unexpected empty filename!" ) ? void (0) : __assert_fail ("!Input.isEmpty() && \"Unexpected empty filename!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 554, __extension__ __PRETTY_FUNCTION__)); | ||||
555 | setCurrentInput(Input); | ||||
556 | setCompilerInstance(&CI); | ||||
557 | |||||
558 | bool HasBegunSourceFile = false; | ||||
559 | bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled && | ||||
560 | usesPreprocessorOnly(); | ||||
561 | if (!BeginInvocation(CI)) | ||||
562 | goto failure; | ||||
563 | |||||
564 | // If we're replaying the build of an AST file, import it and set up | ||||
565 | // the initial state from its build. | ||||
566 | if (ReplayASTFile
| ||||
567 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); | ||||
568 | |||||
569 | // The AST unit populates its own diagnostics engine rather than ours. | ||||
570 | IntrusiveRefCntPtr<DiagnosticsEngine> ASTDiags( | ||||
571 | new DiagnosticsEngine(Diags->getDiagnosticIDs(), | ||||
572 | &Diags->getDiagnosticOptions())); | ||||
573 | ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false); | ||||
574 | |||||
575 | // FIXME: What if the input is a memory buffer? | ||||
576 | StringRef InputFile = Input.getFile(); | ||||
577 | |||||
578 | std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile( | ||||
579 | std::string(InputFile), CI.getPCHContainerReader(), | ||||
580 | ASTUnit::LoadPreprocessorOnly, ASTDiags, CI.getFileSystemOpts(), | ||||
581 | CI.getCodeGenOpts().DebugTypeExtRefs); | ||||
582 | if (!AST) | ||||
583 | goto failure; | ||||
584 | |||||
585 | // Options relating to how we treat the input (but not what we do with it) | ||||
586 | // are inherited from the AST unit. | ||||
587 | CI.getHeaderSearchOpts() = AST->getHeaderSearchOpts(); | ||||
588 | CI.getPreprocessorOpts() = AST->getPreprocessorOpts(); | ||||
589 | CI.getLangOpts() = AST->getLangOpts(); | ||||
590 | |||||
591 | // Set the shared objects, these are reset when we finish processing the | ||||
592 | // file, otherwise the CompilerInstance will happily destroy them. | ||||
593 | CI.setFileManager(&AST->getFileManager()); | ||||
594 | CI.createSourceManager(CI.getFileManager()); | ||||
595 | CI.getSourceManager().initializeForReplay(AST->getSourceManager()); | ||||
596 | |||||
597 | // Preload all the module files loaded transitively by the AST unit. Also | ||||
598 | // load all module map files that were parsed as part of building the AST | ||||
599 | // unit. | ||||
600 | if (auto ASTReader = AST->getASTReader()) { | ||||
601 | auto &MM = ASTReader->getModuleManager(); | ||||
602 | auto &PrimaryModule = MM.getPrimaryModule(); | ||||
603 | |||||
604 | for (serialization::ModuleFile &MF : MM) | ||||
605 | if (&MF != &PrimaryModule) | ||||
606 | CI.getFrontendOpts().ModuleFiles.push_back(MF.FileName); | ||||
607 | |||||
608 | ASTReader->visitTopLevelModuleMaps( | ||||
609 | PrimaryModule, [&](const FileEntry *FE) { | ||||
610 | CI.getFrontendOpts().ModuleMapFiles.push_back( | ||||
611 | std::string(FE->getName())); | ||||
612 | }); | ||||
613 | } | ||||
614 | |||||
615 | // Set up the input file for replay purposes. | ||||
616 | auto Kind = AST->getInputKind(); | ||||
617 | if (Kind.getFormat() == InputKind::ModuleMap) { | ||||
618 | Module *ASTModule = | ||||
619 | AST->getPreprocessor().getHeaderSearchInfo().lookupModule( | ||||
620 | AST->getLangOpts().CurrentModule, /*AllowSearch*/ false); | ||||
621 | assert(ASTModule && "module file does not define its own module")(static_cast <bool> (ASTModule && "module file does not define its own module" ) ? void (0) : __assert_fail ("ASTModule && \"module file does not define its own module\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 621, __extension__ __PRETTY_FUNCTION__)); | ||||
622 | Input = FrontendInputFile(ASTModule->PresumedModuleMapFile, Kind); | ||||
623 | } else { | ||||
624 | auto &OldSM = AST->getSourceManager(); | ||||
625 | FileID ID = OldSM.getMainFileID(); | ||||
626 | if (auto *File = OldSM.getFileEntryForID(ID)) | ||||
627 | Input = FrontendInputFile(File->getName(), Kind); | ||||
628 | else | ||||
629 | Input = FrontendInputFile(OldSM.getBufferOrFake(ID), Kind); | ||||
630 | } | ||||
631 | setCurrentInput(Input, std::move(AST)); | ||||
632 | } | ||||
633 | |||||
634 | // AST files follow a very different path, since they share objects via the | ||||
635 | // AST unit. | ||||
636 | if (Input.getKind().getFormat() == InputKind::Precompiled) { | ||||
637 | assert(!usesPreprocessorOnly() && "this case was handled above")(static_cast <bool> (!usesPreprocessorOnly() && "this case was handled above") ? void (0) : __assert_fail ("!usesPreprocessorOnly() && \"this case was handled above\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 637, __extension__ __PRETTY_FUNCTION__)); | ||||
638 | assert(hasASTFileSupport() &&(static_cast <bool> (hasASTFileSupport() && "This action does not have AST file support!" ) ? void (0) : __assert_fail ("hasASTFileSupport() && \"This action does not have AST file support!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 639, __extension__ __PRETTY_FUNCTION__)) | ||||
639 | "This action does not have AST file support!")(static_cast <bool> (hasASTFileSupport() && "This action does not have AST file support!" ) ? void (0) : __assert_fail ("hasASTFileSupport() && \"This action does not have AST file support!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 639, __extension__ __PRETTY_FUNCTION__)); | ||||
640 | |||||
641 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); | ||||
642 | |||||
643 | // FIXME: What if the input is a memory buffer? | ||||
644 | StringRef InputFile = Input.getFile(); | ||||
645 | |||||
646 | std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile( | ||||
647 | std::string(InputFile), CI.getPCHContainerReader(), | ||||
648 | ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts(), | ||||
649 | CI.getCodeGenOpts().DebugTypeExtRefs); | ||||
650 | |||||
651 | if (!AST) | ||||
652 | goto failure; | ||||
653 | |||||
654 | // Inform the diagnostic client we are processing a source file. | ||||
655 | CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr); | ||||
656 | HasBegunSourceFile = true; | ||||
657 | |||||
658 | // Set the shared objects, these are reset when we finish processing the | ||||
659 | // file, otherwise the CompilerInstance will happily destroy them. | ||||
660 | CI.setFileManager(&AST->getFileManager()); | ||||
661 | CI.setSourceManager(&AST->getSourceManager()); | ||||
662 | CI.setPreprocessor(AST->getPreprocessorPtr()); | ||||
663 | Preprocessor &PP = CI.getPreprocessor(); | ||||
664 | PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), | ||||
665 | PP.getLangOpts()); | ||||
666 | CI.setASTContext(&AST->getASTContext()); | ||||
667 | |||||
668 | setCurrentInput(Input, std::move(AST)); | ||||
669 | |||||
670 | // Initialize the action. | ||||
671 | if (!BeginSourceFileAction(CI)) | ||||
672 | goto failure; | ||||
673 | |||||
674 | // Create the AST consumer. | ||||
675 | CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile)); | ||||
676 | if (!CI.hasASTConsumer()) | ||||
677 | goto failure; | ||||
678 | |||||
679 | return true; | ||||
680 | } | ||||
681 | |||||
682 | // Set up the file and source managers, if needed. | ||||
683 | if (!CI.hasFileManager()) { | ||||
684 | if (!CI.createFileManager()) { | ||||
685 | goto failure; | ||||
686 | } | ||||
687 | } | ||||
688 | if (!CI.hasSourceManager()) | ||||
689 | CI.createSourceManager(CI.getFileManager()); | ||||
690 | |||||
691 | // Set up embedding for any specified files. Do this before we load any | ||||
692 | // source files, including the primary module map for the compilation. | ||||
693 | for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) { | ||||
694 | if (auto FE = CI.getFileManager().getFile(F, /*openFile*/true)) | ||||
695 | CI.getSourceManager().setFileIsTransient(*FE); | ||||
696 | else | ||||
697 | CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F; | ||||
698 | } | ||||
699 | if (CI.getFrontendOpts().ModulesEmbedAllFiles) | ||||
700 | CI.getSourceManager().setAllFilesAreTransient(true); | ||||
701 | |||||
702 | // IR files bypass the rest of initialization. | ||||
703 | if (Input.getKind().getLanguage() == Language::LLVM_IR) { | ||||
704 | assert(hasIRSupport() &&(static_cast <bool> (hasIRSupport() && "This action does not have IR file support!" ) ? void (0) : __assert_fail ("hasIRSupport() && \"This action does not have IR file support!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 705, __extension__ __PRETTY_FUNCTION__)) | ||||
705 | "This action does not have IR file support!")(static_cast <bool> (hasIRSupport() && "This action does not have IR file support!" ) ? void (0) : __assert_fail ("hasIRSupport() && \"This action does not have IR file support!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 705, __extension__ __PRETTY_FUNCTION__)); | ||||
706 | |||||
707 | // Inform the diagnostic client we are processing a source file. | ||||
708 | CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr); | ||||
709 | HasBegunSourceFile = true; | ||||
710 | |||||
711 | // Initialize the action. | ||||
712 | if (!BeginSourceFileAction(CI)) | ||||
713 | goto failure; | ||||
714 | |||||
715 | // Initialize the main file entry. | ||||
716 | if (!CI.InitializeSourceManager(CurrentInput)) | ||||
717 | goto failure; | ||||
718 | |||||
719 | return true; | ||||
720 | } | ||||
721 | |||||
722 | // If the implicit PCH include is actually a directory, rather than | ||||
723 | // a single file, search for a suitable PCH file in that directory. | ||||
724 | if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { | ||||
725 | FileManager &FileMgr = CI.getFileManager(); | ||||
726 | PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); | ||||
727 | StringRef PCHInclude = PPOpts.ImplicitPCHInclude; | ||||
728 | std::string SpecificModuleCachePath = CI.getSpecificModuleCachePath(); | ||||
729 | if (auto PCHDir = FileMgr.getDirectory(PCHInclude)) { | ||||
730 | std::error_code EC; | ||||
731 | SmallString<128> DirNative; | ||||
732 | llvm::sys::path::native((*PCHDir)->getName(), DirNative); | ||||
733 | bool Found = false; | ||||
734 | llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); | ||||
735 | for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), | ||||
736 | DirEnd; | ||||
737 | Dir != DirEnd && !EC; Dir.increment(EC)) { | ||||
738 | // Check whether this is an acceptable AST file. | ||||
739 | if (ASTReader::isAcceptableASTFile( | ||||
740 | Dir->path(), FileMgr, CI.getPCHContainerReader(), | ||||
741 | CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(), | ||||
742 | SpecificModuleCachePath)) { | ||||
743 | PPOpts.ImplicitPCHInclude = std::string(Dir->path()); | ||||
744 | Found = true; | ||||
745 | break; | ||||
746 | } | ||||
747 | } | ||||
748 | |||||
749 | if (!Found) { | ||||
750 | CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; | ||||
751 | goto failure; | ||||
752 | } | ||||
753 | } | ||||
754 | } | ||||
755 | |||||
756 | // Set up the preprocessor if needed. When parsing model files the | ||||
757 | // preprocessor of the original source is reused. | ||||
758 | if (!isModelParsingAction()) | ||||
759 | CI.createPreprocessor(getTranslationUnitKind()); | ||||
760 | |||||
761 | // Inform the diagnostic client we are processing a source file. | ||||
762 | CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), | ||||
763 | &CI.getPreprocessor()); | ||||
764 | HasBegunSourceFile = true; | ||||
765 | |||||
766 | // Initialize the main file entry. | ||||
767 | if (!CI.InitializeSourceManager(Input)) | ||||
768 | goto failure; | ||||
769 | |||||
770 | // For module map files, we first parse the module map and synthesize a | ||||
771 | // "<module-includes>" buffer before more conventional processing. | ||||
772 | if (Input.getKind().getFormat() == InputKind::ModuleMap) { | ||||
773 | CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap); | ||||
774 | |||||
775 | std::string PresumedModuleMapFile; | ||||
776 | unsigned OffsetToContents; | ||||
777 | if (loadModuleMapForModuleBuild(CI, Input.isSystem(), | ||||
778 | Input.isPreprocessed(), | ||||
779 | PresumedModuleMapFile, OffsetToContents)) | ||||
780 | goto failure; | ||||
781 | |||||
782 | auto *CurrentModule = prepareToBuildModule(CI, Input.getFile()); | ||||
783 | if (!CurrentModule) | ||||
784 | goto failure; | ||||
785 | |||||
786 | CurrentModule->PresumedModuleMapFile = PresumedModuleMapFile; | ||||
787 | |||||
788 | if (OffsetToContents) | ||||
789 | // If the module contents are in the same file, skip to them. | ||||
790 | CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true); | ||||
791 | else { | ||||
792 | // Otherwise, convert the module description to a suitable input buffer. | ||||
793 | auto Buffer = getInputBufferForModule(CI, CurrentModule); | ||||
794 | if (!Buffer) | ||||
795 | goto failure; | ||||
796 | |||||
797 | // Reinitialize the main file entry to refer to the new input. | ||||
798 | auto Kind = CurrentModule->IsSystem ? SrcMgr::C_System : SrcMgr::C_User; | ||||
799 | auto &SourceMgr = CI.getSourceManager(); | ||||
800 | auto BufferID = SourceMgr.createFileID(std::move(Buffer), Kind); | ||||
801 | assert(BufferID.isValid() && "couldn't create module buffer ID")(static_cast <bool> (BufferID.isValid() && "couldn't create module buffer ID" ) ? void (0) : __assert_fail ("BufferID.isValid() && \"couldn't create module buffer ID\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 801, __extension__ __PRETTY_FUNCTION__)); | ||||
802 | SourceMgr.setMainFileID(BufferID); | ||||
803 | } | ||||
804 | } | ||||
805 | |||||
806 | // Initialize the action. | ||||
807 | if (!BeginSourceFileAction(CI)) | ||||
808 | goto failure; | ||||
809 | |||||
810 | // If we were asked to load any module map files, do so now. | ||||
811 | for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) { | ||||
812 | if (auto File = CI.getFileManager().getFile(Filename)) | ||||
813 | CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile( | ||||
814 | *File, /*IsSystem*/false); | ||||
815 | else | ||||
816 | CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename; | ||||
817 | } | ||||
818 | |||||
819 | // Add a module declaration scope so that modules from -fmodule-map-file | ||||
820 | // arguments may shadow modules found implicitly in search paths. | ||||
821 | CI.getPreprocessor() | ||||
822 | .getHeaderSearchInfo() | ||||
823 | .getModuleMap() | ||||
824 | .finishModuleDeclarationScope(); | ||||
825 | |||||
826 | // Create the AST context and consumer unless this is a preprocessor only | ||||
827 | // action. | ||||
828 | if (!usesPreprocessorOnly()) { | ||||
829 | // Parsing a model file should reuse the existing ASTContext. | ||||
830 | if (!isModelParsingAction()) | ||||
831 | CI.createASTContext(); | ||||
832 | |||||
833 | // For preprocessed files, check if the first line specifies the original | ||||
834 | // source file name with a linemarker. | ||||
835 | std::string PresumedInputFile = std::string(getCurrentFileOrBufferName()); | ||||
836 | if (Input.isPreprocessed()) | ||||
837 | ReadOriginalFileName(CI, PresumedInputFile); | ||||
838 | |||||
839 | std::unique_ptr<ASTConsumer> Consumer = | ||||
840 | CreateWrappedASTConsumer(CI, PresumedInputFile); | ||||
841 | if (!Consumer) | ||||
842 | goto failure; | ||||
843 | |||||
844 | // FIXME: should not overwrite ASTMutationListener when parsing model files? | ||||
845 | if (!isModelParsingAction()) | ||||
846 | CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); | ||||
847 | |||||
848 | if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { | ||||
849 | // Convert headers to PCH and chain them. | ||||
850 | IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader; | ||||
851 | source = createChainedIncludesSource(CI, FinalReader); | ||||
852 | if (!source) | ||||
853 | goto failure; | ||||
854 | CI.setASTReader(static_cast<ASTReader *>(FinalReader.get())); | ||||
855 | CI.getASTContext().setExternalSource(source); | ||||
856 | } else if (CI.getLangOpts().Modules || | ||||
857 | !CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { | ||||
858 | // Use PCM or PCH. | ||||
859 | assert(hasPCHSupport() && "This action does not have PCH support!")(static_cast <bool> (hasPCHSupport() && "This action does not have PCH support!" ) ? void (0) : __assert_fail ("hasPCHSupport() && \"This action does not have PCH support!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 859, __extension__ __PRETTY_FUNCTION__)); | ||||
860 | ASTDeserializationListener *DeserialListener = | ||||
861 | Consumer->GetASTDeserializationListener(); | ||||
862 | bool DeleteDeserialListener = false; | ||||
863 | if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) { | ||||
864 | DeserialListener = new DeserializedDeclsDumper(DeserialListener, | ||||
865 | DeleteDeserialListener); | ||||
866 | DeleteDeserialListener = true; | ||||
867 | } | ||||
868 | if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) { | ||||
869 | DeserialListener = new DeserializedDeclsChecker( | ||||
870 | CI.getASTContext(), | ||||
871 | CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, | ||||
872 | DeserialListener, DeleteDeserialListener); | ||||
873 | DeleteDeserialListener = true; | ||||
874 | } | ||||
875 | if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { | ||||
876 | CI.createPCHExternalASTSource( | ||||
877 | CI.getPreprocessorOpts().ImplicitPCHInclude, | ||||
878 | CI.getPreprocessorOpts().DisablePCHOrModuleValidation, | ||||
879 | CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, | ||||
880 | DeserialListener, DeleteDeserialListener); | ||||
881 | if (!CI.getASTContext().getExternalSource()) | ||||
882 | goto failure; | ||||
883 | } | ||||
884 | // If modules are enabled, create the AST reader before creating | ||||
885 | // any builtins, so that all declarations know that they might be | ||||
886 | // extended by an external source. | ||||
887 | if (CI.getLangOpts().Modules
| ||||
888 | !CI.getASTContext().getExternalSource()) { | ||||
889 | CI.createASTReader(); | ||||
890 | CI.getASTReader()->setDeserializationListener(DeserialListener, | ||||
891 | DeleteDeserialListener); | ||||
892 | } | ||||
893 | } | ||||
894 | |||||
895 | CI.setASTConsumer(std::move(Consumer)); | ||||
| |||||
896 | if (!CI.hasASTConsumer()) | ||||
897 | goto failure; | ||||
898 | } | ||||
899 | |||||
900 | // Initialize built-in info as long as we aren't using an external AST | ||||
901 | // source. | ||||
902 | if (CI.getLangOpts().Modules || !CI.hasASTContext() || | ||||
903 | !CI.getASTContext().getExternalSource()) { | ||||
904 | Preprocessor &PP = CI.getPreprocessor(); | ||||
905 | PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), | ||||
906 | PP.getLangOpts()); | ||||
907 | } else { | ||||
908 | // FIXME: If this is a problem, recover from it by creating a multiplex | ||||
909 | // source. | ||||
910 | assert((!CI.getLangOpts().Modules || CI.getASTReader()) &&(static_cast <bool> ((!CI.getLangOpts().Modules || CI.getASTReader ()) && "modules enabled but created an external source that " "doesn't support modules") ? void (0) : __assert_fail ("(!CI.getLangOpts().Modules || CI.getASTReader()) && \"modules enabled but created an external source that \" \"doesn't support modules\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 912, __extension__ __PRETTY_FUNCTION__)) | ||||
911 | "modules enabled but created an external source that "(static_cast <bool> ((!CI.getLangOpts().Modules || CI.getASTReader ()) && "modules enabled but created an external source that " "doesn't support modules") ? void (0) : __assert_fail ("(!CI.getLangOpts().Modules || CI.getASTReader()) && \"modules enabled but created an external source that \" \"doesn't support modules\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 912, __extension__ __PRETTY_FUNCTION__)) | ||||
912 | "doesn't support modules")(static_cast <bool> ((!CI.getLangOpts().Modules || CI.getASTReader ()) && "modules enabled but created an external source that " "doesn't support modules") ? void (0) : __assert_fail ("(!CI.getLangOpts().Modules || CI.getASTReader()) && \"modules enabled but created an external source that \" \"doesn't support modules\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 912, __extension__ __PRETTY_FUNCTION__)); | ||||
913 | } | ||||
914 | |||||
915 | // If we were asked to load any module files, do so now. | ||||
916 | for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles) | ||||
917 | if (!CI.loadModuleFile(ModuleFile)) | ||||
918 | goto failure; | ||||
919 | |||||
920 | // If there is a layout overrides file, attach an external AST source that | ||||
921 | // provides the layouts from that file. | ||||
922 | if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && | ||||
923 | CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { | ||||
924 | IntrusiveRefCntPtr<ExternalASTSource> | ||||
925 | Override(new LayoutOverrideSource( | ||||
926 | CI.getFrontendOpts().OverrideRecordLayoutsFile)); | ||||
927 | CI.getASTContext().setExternalSource(Override); | ||||
928 | } | ||||
929 | |||||
930 | return true; | ||||
931 | |||||
932 | // If we failed, reset state since the client will not end up calling the | ||||
933 | // matching EndSourceFile(). | ||||
934 | failure: | ||||
935 | if (HasBegunSourceFile) | ||||
936 | CI.getDiagnosticClient().EndSourceFile(); | ||||
937 | CI.clearOutputFiles(/*EraseFiles=*/true); | ||||
938 | CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); | ||||
939 | setCurrentInput(FrontendInputFile()); | ||||
940 | setCompilerInstance(nullptr); | ||||
941 | return false; | ||||
942 | } | ||||
943 | |||||
944 | llvm::Error FrontendAction::Execute() { | ||||
945 | CompilerInstance &CI = getCompilerInstance(); | ||||
946 | |||||
947 | if (CI.hasFrontendTimer()) { | ||||
948 | llvm::TimeRegion Timer(CI.getFrontendTimer()); | ||||
949 | ExecuteAction(); | ||||
950 | } | ||||
951 | else ExecuteAction(); | ||||
952 | |||||
953 | // If we are supposed to rebuild the global module index, do so now unless | ||||
954 | // there were any module-build failures. | ||||
955 | if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() && | ||||
956 | CI.hasPreprocessor()) { | ||||
957 | StringRef Cache = | ||||
958 | CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath(); | ||||
959 | if (!Cache.empty()) { | ||||
960 | if (llvm::Error Err = GlobalModuleIndex::writeIndex( | ||||
961 | CI.getFileManager(), CI.getPCHContainerReader(), Cache)) { | ||||
962 | // FIXME this drops the error on the floor, but | ||||
963 | // Index/pch-from-libclang.c seems to rely on dropping at least some of | ||||
964 | // the error conditions! | ||||
965 | consumeError(std::move(Err)); | ||||
966 | } | ||||
967 | } | ||||
968 | } | ||||
969 | |||||
970 | return llvm::Error::success(); | ||||
971 | } | ||||
972 | |||||
973 | void FrontendAction::EndSourceFile() { | ||||
974 | CompilerInstance &CI = getCompilerInstance(); | ||||
975 | |||||
976 | // Inform the diagnostic client we are done with this source file. | ||||
977 | CI.getDiagnosticClient().EndSourceFile(); | ||||
978 | |||||
979 | // Inform the preprocessor we are done. | ||||
980 | if (CI.hasPreprocessor()) | ||||
981 | CI.getPreprocessor().EndSourceFile(); | ||||
982 | |||||
983 | // Finalize the action. | ||||
984 | EndSourceFileAction(); | ||||
985 | |||||
986 | // Sema references the ast consumer, so reset sema first. | ||||
987 | // | ||||
988 | // FIXME: There is more per-file stuff we could just drop here? | ||||
989 | bool DisableFree = CI.getFrontendOpts().DisableFree; | ||||
990 | if (DisableFree) { | ||||
991 | CI.resetAndLeakSema(); | ||||
992 | CI.resetAndLeakASTContext(); | ||||
993 | llvm::BuryPointer(CI.takeASTConsumer().get()); | ||||
994 | } else { | ||||
995 | CI.setSema(nullptr); | ||||
996 | CI.setASTContext(nullptr); | ||||
997 | CI.setASTConsumer(nullptr); | ||||
998 | } | ||||
999 | |||||
1000 | if (CI.getFrontendOpts().ShowStats) { | ||||
1001 | llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n"; | ||||
1002 | CI.getPreprocessor().PrintStats(); | ||||
1003 | CI.getPreprocessor().getIdentifierTable().PrintStats(); | ||||
1004 | CI.getPreprocessor().getHeaderSearchInfo().PrintStats(); | ||||
1005 | CI.getSourceManager().PrintStats(); | ||||
1006 | llvm::errs() << "\n"; | ||||
1007 | } | ||||
1008 | |||||
1009 | // Cleanup the output streams, and erase the output files if instructed by the | ||||
1010 | // FrontendAction. | ||||
1011 | CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles()); | ||||
1012 | |||||
1013 | if (isCurrentFileAST()) { | ||||
1014 | if (DisableFree) { | ||||
1015 | CI.resetAndLeakPreprocessor(); | ||||
1016 | CI.resetAndLeakSourceManager(); | ||||
1017 | CI.resetAndLeakFileManager(); | ||||
1018 | llvm::BuryPointer(std::move(CurrentASTUnit)); | ||||
1019 | } else { | ||||
1020 | CI.setPreprocessor(nullptr); | ||||
1021 | CI.setSourceManager(nullptr); | ||||
1022 | CI.setFileManager(nullptr); | ||||
1023 | } | ||||
1024 | } | ||||
1025 | |||||
1026 | setCompilerInstance(nullptr); | ||||
1027 | setCurrentInput(FrontendInputFile()); | ||||
1028 | CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); | ||||
1029 | } | ||||
1030 | |||||
1031 | bool FrontendAction::shouldEraseOutputFiles() { | ||||
1032 | return getCompilerInstance().getDiagnostics().hasErrorOccurred(); | ||||
1033 | } | ||||
1034 | |||||
1035 | //===----------------------------------------------------------------------===// | ||||
1036 | // Utility Actions | ||||
1037 | //===----------------------------------------------------------------------===// | ||||
1038 | |||||
1039 | void ASTFrontendAction::ExecuteAction() { | ||||
1040 | CompilerInstance &CI = getCompilerInstance(); | ||||
1041 | if (!CI.hasPreprocessor()) | ||||
1042 | return; | ||||
1043 | |||||
1044 | // FIXME: Move the truncation aspect of this into Sema, we delayed this till | ||||
1045 | // here so the source manager would be initialized. | ||||
1046 | if (hasCodeCompletionSupport() && | ||||
1047 | !CI.getFrontendOpts().CodeCompletionAt.FileName.empty()) | ||||
1048 | CI.createCodeCompletionConsumer(); | ||||
1049 | |||||
1050 | // Use a code completion consumer? | ||||
1051 | CodeCompleteConsumer *CompletionConsumer = nullptr; | ||||
1052 | if (CI.hasCodeCompletionConsumer()) | ||||
1053 | CompletionConsumer = &CI.getCodeCompletionConsumer(); | ||||
1054 | |||||
1055 | if (!CI.hasSema()) | ||||
1056 | CI.createSema(getTranslationUnitKind(), CompletionConsumer); | ||||
1057 | |||||
1058 | ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats, | ||||
1059 | CI.getFrontendOpts().SkipFunctionBodies); | ||||
1060 | } | ||||
1061 | |||||
1062 | void PluginASTAction::anchor() { } | ||||
1063 | |||||
1064 | std::unique_ptr<ASTConsumer> | ||||
1065 | PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI, | ||||
1066 | StringRef InFile) { | ||||
1067 | llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!")::llvm::llvm_unreachable_internal("Invalid CreateASTConsumer on preprocessor action!" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/lib/Frontend/FrontendAction.cpp" , 1067); | ||||
1068 | } | ||||
1069 | |||||
1070 | bool WrapperFrontendAction::PrepareToExecuteAction(CompilerInstance &CI) { | ||||
1071 | return WrappedAction->PrepareToExecuteAction(CI); | ||||
1072 | } | ||||
1073 | std::unique_ptr<ASTConsumer> | ||||
1074 | WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI, | ||||
1075 | StringRef InFile) { | ||||
1076 | return WrappedAction->CreateASTConsumer(CI, InFile); | ||||
1077 | } | ||||
1078 | bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) { | ||||
1079 | return WrappedAction->BeginInvocation(CI); | ||||
1080 | } | ||||
1081 | bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI) { | ||||
1082 | WrappedAction->setCurrentInput(getCurrentInput()); | ||||
1083 | WrappedAction->setCompilerInstance(&CI); | ||||
1084 | auto Ret = WrappedAction->BeginSourceFileAction(CI); | ||||
1085 | // BeginSourceFileAction may change CurrentInput, e.g. during module builds. | ||||
1086 | setCurrentInput(WrappedAction->getCurrentInput()); | ||||
1087 | return Ret; | ||||
1088 | } | ||||
1089 | void WrapperFrontendAction::ExecuteAction() { | ||||
1090 | WrappedAction->ExecuteAction(); | ||||
1091 | } | ||||
1092 | void WrapperFrontendAction::EndSourceFile() { WrappedAction->EndSourceFile(); } | ||||
1093 | void WrapperFrontendAction::EndSourceFileAction() { | ||||
1094 | WrappedAction->EndSourceFileAction(); | ||||
1095 | } | ||||
1096 | bool WrapperFrontendAction::shouldEraseOutputFiles() { | ||||
1097 | return WrappedAction->shouldEraseOutputFiles(); | ||||
1098 | } | ||||
1099 | |||||
1100 | bool WrapperFrontendAction::usesPreprocessorOnly() const { | ||||
1101 | return WrappedAction->usesPreprocessorOnly(); | ||||
1102 | } | ||||
1103 | TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() { | ||||
1104 | return WrappedAction->getTranslationUnitKind(); | ||||
1105 | } | ||||
1106 | bool WrapperFrontendAction::hasPCHSupport() const { | ||||
1107 | return WrappedAction->hasPCHSupport(); | ||||
1108 | } | ||||
1109 | bool WrapperFrontendAction::hasASTFileSupport() const { | ||||
1110 | return WrappedAction->hasASTFileSupport(); | ||||
1111 | } | ||||
1112 | bool WrapperFrontendAction::hasIRSupport() const { | ||||
1113 | return WrappedAction->hasIRSupport(); | ||||
1114 | } | ||||
1115 | bool WrapperFrontendAction::hasCodeCompletionSupport() const { | ||||
1116 | return WrappedAction->hasCodeCompletionSupport(); | ||||
1117 | } | ||||
1118 | |||||
1119 | WrapperFrontendAction::WrapperFrontendAction( | ||||
1120 | std::unique_ptr<FrontendAction> WrappedAction) | ||||
1121 | : WrappedAction(std::move(WrappedAction)) {} | ||||
1122 |
1 | //===-- FrontendAction.h - Generic Frontend Action Interface ----*- 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 | /// \file |
10 | /// Defines the clang::FrontendAction interface and various convenience |
11 | /// abstract classes (clang::ASTFrontendAction, clang::PluginASTAction, |
12 | /// clang::PreprocessorFrontendAction, and clang::WrapperFrontendAction) |
13 | /// derived from it. |
14 | /// |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H |
18 | #define LLVM_CLANG_FRONTEND_FRONTENDACTION_H |
19 | |
20 | #include "clang/AST/ASTConsumer.h" |
21 | #include "clang/Basic/LLVM.h" |
22 | #include "clang/Basic/LangOptions.h" |
23 | #include "clang/Frontend/ASTUnit.h" |
24 | #include "clang/Frontend/FrontendOptions.h" |
25 | #include "llvm/ADT/StringRef.h" |
26 | #include "llvm/Support/Error.h" |
27 | #include <memory> |
28 | #include <string> |
29 | #include <vector> |
30 | |
31 | namespace clang { |
32 | class ASTMergeAction; |
33 | class CompilerInstance; |
34 | |
35 | /// Abstract base class for actions which can be performed by the frontend. |
36 | class FrontendAction { |
37 | FrontendInputFile CurrentInput; |
38 | std::unique_ptr<ASTUnit> CurrentASTUnit; |
39 | CompilerInstance *Instance; |
40 | friend class ASTMergeAction; |
41 | friend class WrapperFrontendAction; |
42 | |
43 | private: |
44 | std::unique_ptr<ASTConsumer> CreateWrappedASTConsumer(CompilerInstance &CI, |
45 | StringRef InFile); |
46 | |
47 | protected: |
48 | /// @name Implementation Action Interface |
49 | /// @{ |
50 | |
51 | /// Prepare to execute the action on the given CompilerInstance. |
52 | /// |
53 | /// This is called before executing the action on any inputs, and can modify |
54 | /// the configuration as needed (including adjusting the input list). |
55 | virtual bool PrepareToExecuteAction(CompilerInstance &CI) { return true; } |
56 | |
57 | /// Create the AST consumer object for this action, if supported. |
58 | /// |
59 | /// This routine is called as part of BeginSourceFile(), which will |
60 | /// fail if the AST consumer cannot be created. This will not be called if the |
61 | /// action has indicated that it only uses the preprocessor. |
62 | /// |
63 | /// \param CI - The current compiler instance, provided as a convenience, see |
64 | /// getCompilerInstance(). |
65 | /// |
66 | /// \param InFile - The current input file, provided as a convenience, see |
67 | /// getCurrentFile(). |
68 | /// |
69 | /// \return The new AST consumer, or null on failure. |
70 | virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, |
71 | StringRef InFile) = 0; |
72 | |
73 | /// Callback before starting processing a single input, giving the |
74 | /// opportunity to modify the CompilerInvocation or do some other action |
75 | /// before BeginSourceFileAction is called. |
76 | /// |
77 | /// \return True on success; on failure BeginSourceFileAction(), |
78 | /// ExecuteAction() and EndSourceFileAction() will not be called. |
79 | virtual bool BeginInvocation(CompilerInstance &CI) { return true; } |
80 | |
81 | /// Callback at the start of processing a single input. |
82 | /// |
83 | /// \return True on success; on failure ExecutionAction() and |
84 | /// EndSourceFileAction() will not be called. |
85 | virtual bool BeginSourceFileAction(CompilerInstance &CI) { |
86 | return true; |
87 | } |
88 | |
89 | /// Callback to run the program action, using the initialized |
90 | /// compiler instance. |
91 | /// |
92 | /// This is guaranteed to only be called between BeginSourceFileAction() |
93 | /// and EndSourceFileAction(). |
94 | virtual void ExecuteAction() = 0; |
95 | |
96 | /// Callback at the end of processing a single input. |
97 | /// |
98 | /// This is guaranteed to only be called following a successful call to |
99 | /// BeginSourceFileAction (and BeginSourceFile). |
100 | virtual void EndSourceFileAction() {} |
101 | |
102 | /// Callback at the end of processing a single input, to determine |
103 | /// if the output files should be erased or not. |
104 | /// |
105 | /// By default it returns true if a compiler error occurred. |
106 | /// This is guaranteed to only be called following a successful call to |
107 | /// BeginSourceFileAction (and BeginSourceFile). |
108 | virtual bool shouldEraseOutputFiles(); |
109 | |
110 | /// @} |
111 | |
112 | public: |
113 | FrontendAction(); |
114 | virtual ~FrontendAction(); |
115 | |
116 | /// @name Compiler Instance Access |
117 | /// @{ |
118 | |
119 | CompilerInstance &getCompilerInstance() const { |
120 | assert(Instance && "Compiler instance not registered!")(static_cast <bool> (Instance && "Compiler instance not registered!" ) ? void (0) : __assert_fail ("Instance && \"Compiler instance not registered!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/include/clang/Frontend/FrontendAction.h" , 120, __extension__ __PRETTY_FUNCTION__)); |
121 | return *Instance; |
122 | } |
123 | |
124 | void setCompilerInstance(CompilerInstance *Value) { Instance = Value; } |
125 | |
126 | /// @} |
127 | /// @name Current File Information |
128 | /// @{ |
129 | |
130 | bool isCurrentFileAST() const { |
131 | assert(!CurrentInput.isEmpty() && "No current file!")(static_cast <bool> (!CurrentInput.isEmpty() && "No current file!") ? void (0) : __assert_fail ("!CurrentInput.isEmpty() && \"No current file!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/include/clang/Frontend/FrontendAction.h" , 131, __extension__ __PRETTY_FUNCTION__)); |
132 | return (bool)CurrentASTUnit; |
133 | } |
134 | |
135 | const FrontendInputFile &getCurrentInput() const { |
136 | return CurrentInput; |
137 | } |
138 | |
139 | StringRef getCurrentFile() const { |
140 | assert(!CurrentInput.isEmpty() && "No current file!")(static_cast <bool> (!CurrentInput.isEmpty() && "No current file!") ? void (0) : __assert_fail ("!CurrentInput.isEmpty() && \"No current file!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/include/clang/Frontend/FrontendAction.h" , 140, __extension__ __PRETTY_FUNCTION__)); |
141 | return CurrentInput.getFile(); |
142 | } |
143 | |
144 | StringRef getCurrentFileOrBufferName() const { |
145 | assert(!CurrentInput.isEmpty() && "No current file!")(static_cast <bool> (!CurrentInput.isEmpty() && "No current file!") ? void (0) : __assert_fail ("!CurrentInput.isEmpty() && \"No current file!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/include/clang/Frontend/FrontendAction.h" , 145, __extension__ __PRETTY_FUNCTION__)); |
146 | return CurrentInput.isFile() |
147 | ? CurrentInput.getFile() |
148 | : CurrentInput.getBuffer().getBufferIdentifier(); |
149 | } |
150 | |
151 | InputKind getCurrentFileKind() const { |
152 | assert(!CurrentInput.isEmpty() && "No current file!")(static_cast <bool> (!CurrentInput.isEmpty() && "No current file!") ? void (0) : __assert_fail ("!CurrentInput.isEmpty() && \"No current file!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/include/clang/Frontend/FrontendAction.h" , 152, __extension__ __PRETTY_FUNCTION__)); |
153 | return CurrentInput.getKind(); |
154 | } |
155 | |
156 | ASTUnit &getCurrentASTUnit() const { |
157 | assert(CurrentASTUnit && "No current AST unit!")(static_cast <bool> (CurrentASTUnit && "No current AST unit!" ) ? void (0) : __assert_fail ("CurrentASTUnit && \"No current AST unit!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/clang/include/clang/Frontend/FrontendAction.h" , 157, __extension__ __PRETTY_FUNCTION__)); |
158 | return *CurrentASTUnit; |
159 | } |
160 | |
161 | Module *getCurrentModule() const; |
162 | |
163 | std::unique_ptr<ASTUnit> takeCurrentASTUnit() { |
164 | return std::move(CurrentASTUnit); |
165 | } |
166 | |
167 | void setCurrentInput(const FrontendInputFile &CurrentInput, |
168 | std::unique_ptr<ASTUnit> AST = nullptr); |
169 | |
170 | /// @} |
171 | /// @name Supported Modes |
172 | /// @{ |
173 | |
174 | /// Is this action invoked on a model file? |
175 | /// |
176 | /// Model files are incomplete translation units that relies on type |
177 | /// information from another translation unit. Check ParseModelFileAction for |
178 | /// details. |
179 | virtual bool isModelParsingAction() const { return false; } |
180 | |
181 | /// Does this action only use the preprocessor? |
182 | /// |
183 | /// If so no AST context will be created and this action will be invalid |
184 | /// with AST file inputs. |
185 | virtual bool usesPreprocessorOnly() const = 0; |
186 | |
187 | /// For AST-based actions, the kind of translation unit we're handling. |
188 | virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; } |
189 | |
190 | /// Does this action support use with PCH? |
191 | virtual bool hasPCHSupport() const { return true; } |
192 | |
193 | /// Does this action support use with AST files? |
194 | virtual bool hasASTFileSupport() const { return true; } |
195 | |
196 | /// Does this action support use with IR files? |
197 | virtual bool hasIRSupport() const { return false; } |
198 | |
199 | /// Does this action support use with code completion? |
200 | virtual bool hasCodeCompletionSupport() const { return false; } |
201 | |
202 | /// @} |
203 | /// @name Public Action Interface |
204 | /// @{ |
205 | |
206 | /// Prepare the action to execute on the given compiler instance. |
207 | bool PrepareToExecute(CompilerInstance &CI) { |
208 | return PrepareToExecuteAction(CI); |
209 | } |
210 | |
211 | /// Prepare the action for processing the input file \p Input. |
212 | /// |
213 | /// This is run after the options and frontend have been initialized, |
214 | /// but prior to executing any per-file processing. |
215 | /// |
216 | /// \param CI - The compiler instance this action is being run from. The |
217 | /// action may store and use this object up until the matching EndSourceFile |
218 | /// action. |
219 | /// |
220 | /// \param Input - The input filename and kind. Some input kinds are handled |
221 | /// specially, for example AST inputs, since the AST file itself contains |
222 | /// several objects which would normally be owned by the |
223 | /// CompilerInstance. When processing AST input files, these objects should |
224 | /// generally not be initialized in the CompilerInstance -- they will |
225 | /// automatically be shared with the AST file in between |
226 | /// BeginSourceFile() and EndSourceFile(). |
227 | /// |
228 | /// \return True on success; on failure the compilation of this file should |
229 | /// be aborted and neither Execute() nor EndSourceFile() should be called. |
230 | bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input); |
231 | |
232 | /// Set the source manager's main input file, and run the action. |
233 | llvm::Error Execute(); |
234 | |
235 | /// Perform any per-file post processing, deallocate per-file |
236 | /// objects, and run statistics and output file cleanup code. |
237 | virtual void EndSourceFile(); |
238 | |
239 | /// @} |
240 | }; |
241 | |
242 | /// Abstract base class to use for AST consumer-based frontend actions. |
243 | class ASTFrontendAction : public FrontendAction { |
244 | protected: |
245 | /// Implement the ExecuteAction interface by running Sema on |
246 | /// the already-initialized AST consumer. |
247 | /// |
248 | /// This will also take care of instantiating a code completion consumer if |
249 | /// the user requested it and the action supports it. |
250 | void ExecuteAction() override; |
251 | |
252 | public: |
253 | ASTFrontendAction() {} |
254 | bool usesPreprocessorOnly() const override { return false; } |
255 | }; |
256 | |
257 | class PluginASTAction : public ASTFrontendAction { |
258 | virtual void anchor(); |
259 | public: |
260 | std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, |
261 | StringRef InFile) override = 0; |
262 | |
263 | /// Parse the given plugin command line arguments. |
264 | /// |
265 | /// \param CI - The compiler instance, for use in reporting diagnostics. |
266 | /// \return True if the parsing succeeded; otherwise the plugin will be |
267 | /// destroyed and no action run. The plugin is responsible for using the |
268 | /// CompilerInstance's Diagnostic object to report errors. |
269 | virtual bool ParseArgs(const CompilerInstance &CI, |
270 | const std::vector<std::string> &arg) = 0; |
271 | |
272 | enum ActionType { |
273 | Cmdline, ///< Action is determined by the cc1 command-line |
274 | ReplaceAction, ///< Replace the main action |
275 | AddBeforeMainAction, ///< Execute the action before the main action |
276 | AddAfterMainAction ///< Execute the action after the main action |
277 | }; |
278 | /// Get the action type for this plugin |
279 | /// |
280 | /// \return The action type. If the type is Cmdline then by default the |
281 | /// plugin does nothing and what it does is determined by the cc1 |
282 | /// command-line. |
283 | virtual ActionType getActionType() { return Cmdline; } |
284 | }; |
285 | |
286 | /// Abstract base class to use for preprocessor-based frontend actions. |
287 | class PreprocessorFrontendAction : public FrontendAction { |
288 | protected: |
289 | /// Provide a default implementation which returns aborts; |
290 | /// this method should never be called by FrontendAction clients. |
291 | std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, |
292 | StringRef InFile) override; |
293 | |
294 | public: |
295 | bool usesPreprocessorOnly() const override { return true; } |
296 | }; |
297 | |
298 | /// A frontend action which simply wraps some other runtime-specified |
299 | /// frontend action. |
300 | /// |
301 | /// Deriving from this class allows an action to inject custom logic around |
302 | /// some existing action's behavior. It implements every virtual method in |
303 | /// the FrontendAction interface by forwarding to the wrapped action. |
304 | class WrapperFrontendAction : public FrontendAction { |
305 | protected: |
306 | std::unique_ptr<FrontendAction> WrappedAction; |
307 | |
308 | bool PrepareToExecuteAction(CompilerInstance &CI) override; |
309 | std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, |
310 | StringRef InFile) override; |
311 | bool BeginInvocation(CompilerInstance &CI) override; |
312 | bool BeginSourceFileAction(CompilerInstance &CI) override; |
313 | void ExecuteAction() override; |
314 | void EndSourceFile() override; |
315 | void EndSourceFileAction() override; |
316 | bool shouldEraseOutputFiles() override; |
317 | |
318 | public: |
319 | /// Construct a WrapperFrontendAction from an existing action, taking |
320 | /// ownership of it. |
321 | WrapperFrontendAction(std::unique_ptr<FrontendAction> WrappedAction); |
322 | |
323 | bool usesPreprocessorOnly() const override; |
324 | TranslationUnitKind getTranslationUnitKind() override; |
325 | bool hasPCHSupport() const override; |
326 | bool hasASTFileSupport() const override; |
327 | bool hasIRSupport() const override; |
328 | bool hasCodeCompletionSupport() const override; |
329 | }; |
330 | |
331 | } // end namespace clang |
332 | |
333 | #endif |