1 | //===-- CompilerInstance.h - Clang Compiler Instance ------------*- 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 | #ifndef LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ |
10 | #define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ |
11 | |
12 | #include "clang/AST/ASTConsumer.h" |
13 | #include "clang/Basic/Diagnostic.h" |
14 | #include "clang/Basic/SourceManager.h" |
15 | #include "clang/Basic/TargetInfo.h" |
16 | #include "clang/Frontend/CompilerInvocation.h" |
17 | #include "clang/Frontend/PCHContainerOperations.h" |
18 | #include "clang/Frontend/Utils.h" |
19 | #include "clang/Lex/HeaderSearchOptions.h" |
20 | #include "clang/Lex/ModuleLoader.h" |
21 | #include "llvm/ADT/ArrayRef.h" |
22 | #include "llvm/ADT/DenseMap.h" |
23 | #include "llvm/ADT/IntrusiveRefCntPtr.h" |
24 | #include "llvm/ADT/StringRef.h" |
25 | #include "llvm/Support/BuryPointer.h" |
26 | #include "llvm/Support/FileSystem.h" |
27 | #include <cassert> |
28 | #include <list> |
29 | #include <memory> |
30 | #include <optional> |
31 | #include <string> |
32 | #include <utility> |
33 | |
34 | namespace llvm { |
35 | class raw_fd_ostream; |
36 | class Timer; |
37 | class TimerGroup; |
38 | } |
39 | |
40 | namespace clang { |
41 | class ASTContext; |
42 | class ASTReader; |
43 | |
44 | namespace serialization { |
45 | class ModuleFile; |
46 | } |
47 | |
48 | class CodeCompleteConsumer; |
49 | class DiagnosticsEngine; |
50 | class DiagnosticConsumer; |
51 | class FileManager; |
52 | class FrontendAction; |
53 | class InMemoryModuleCache; |
54 | class Module; |
55 | class Preprocessor; |
56 | class Sema; |
57 | class SourceManager; |
58 | class TargetInfo; |
59 | enum class DisableValidationForModuleKind; |
60 | |
61 | /// CompilerInstance - Helper class for managing a single instance of the Clang |
62 | /// compiler. |
63 | /// |
64 | /// The CompilerInstance serves two purposes: |
65 | /// (1) It manages the various objects which are necessary to run the compiler, |
66 | /// for example the preprocessor, the target information, and the AST |
67 | /// context. |
68 | /// (2) It provides utility routines for constructing and manipulating the |
69 | /// common Clang objects. |
70 | /// |
71 | /// The compiler instance generally owns the instance of all the objects that it |
72 | /// manages. However, clients can still share objects by manually setting the |
73 | /// object and retaking ownership prior to destroying the CompilerInstance. |
74 | /// |
75 | /// The compiler instance is intended to simplify clients, but not to lock them |
76 | /// in to the compiler instance for everything. When possible, utility functions |
77 | /// come in two forms; a short form that reuses the CompilerInstance objects, |
78 | /// and a long form that takes explicit instances of any required objects. |
79 | class CompilerInstance : public ModuleLoader { |
80 | /// The options used in this compiler instance. |
81 | std::shared_ptr<CompilerInvocation> Invocation; |
82 | |
83 | /// The diagnostics engine instance. |
84 | IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; |
85 | |
86 | /// The target being compiled for. |
87 | IntrusiveRefCntPtr<TargetInfo> Target; |
88 | |
89 | /// Auxiliary Target info. |
90 | IntrusiveRefCntPtr<TargetInfo> AuxTarget; |
91 | |
92 | /// The file manager. |
93 | IntrusiveRefCntPtr<FileManager> FileMgr; |
94 | |
95 | /// The source manager. |
96 | IntrusiveRefCntPtr<SourceManager> SourceMgr; |
97 | |
98 | /// The cache of PCM files. |
99 | IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache; |
100 | |
101 | /// The preprocessor. |
102 | std::shared_ptr<Preprocessor> PP; |
103 | |
104 | /// The AST context. |
105 | IntrusiveRefCntPtr<ASTContext> Context; |
106 | |
107 | /// An optional sema source that will be attached to sema. |
108 | IntrusiveRefCntPtr<ExternalSemaSource> ExternalSemaSrc; |
109 | |
110 | /// The AST consumer. |
111 | std::unique_ptr<ASTConsumer> Consumer; |
112 | |
113 | /// The code completion consumer. |
114 | std::unique_ptr<CodeCompleteConsumer> CompletionConsumer; |
115 | |
116 | /// The semantic analysis object. |
117 | std::unique_ptr<Sema> TheSema; |
118 | |
119 | /// The frontend timer group. |
120 | std::unique_ptr<llvm::TimerGroup> FrontendTimerGroup; |
121 | |
122 | /// The frontend timer. |
123 | std::unique_ptr<llvm::Timer> FrontendTimer; |
124 | |
125 | /// The ASTReader, if one exists. |
126 | IntrusiveRefCntPtr<ASTReader> TheASTReader; |
127 | |
128 | /// The module dependency collector for crashdumps |
129 | std::shared_ptr<ModuleDependencyCollector> ModuleDepCollector; |
130 | |
131 | /// The module provider. |
132 | std::shared_ptr<PCHContainerOperations> ThePCHContainerOperations; |
133 | |
134 | std::vector<std::shared_ptr<DependencyCollector>> DependencyCollectors; |
135 | |
136 | /// Records the set of modules |
137 | class FailedModulesSet { |
138 | llvm::StringSet<> Failed; |
139 | |
140 | public: |
141 | bool hasAlreadyFailed(StringRef module) { return Failed.count(Key: module) > 0; } |
142 | |
143 | void addFailed(StringRef module) { Failed.insert(key: module); } |
144 | }; |
145 | |
146 | /// The set of modules that failed to build. |
147 | /// |
148 | /// This pointer will be shared among all of the compiler instances created |
149 | /// to (re)build modules, so that once a module fails to build anywhere, |
150 | /// other instances will see that the module has failed and won't try to |
151 | /// build it again. |
152 | std::shared_ptr<FailedModulesSet> FailedModules; |
153 | |
154 | /// The set of top-level modules that has already been built on the |
155 | /// fly as part of this overall compilation action. |
156 | std::map<std::string, std::string, std::less<>> BuiltModules; |
157 | |
158 | /// Should we delete the BuiltModules when we're done? |
159 | bool DeleteBuiltModules = true; |
160 | |
161 | /// The location of the module-import keyword for the last module |
162 | /// import. |
163 | SourceLocation LastModuleImportLoc; |
164 | |
165 | /// The result of the last module import. |
166 | /// |
167 | ModuleLoadResult LastModuleImportResult; |
168 | |
169 | /// Whether we should (re)build the global module index once we |
170 | /// have finished with this translation unit. |
171 | bool BuildGlobalModuleIndex = false; |
172 | |
173 | /// We have a full global module index, with all modules. |
174 | bool HaveFullGlobalModuleIndex = false; |
175 | |
176 | /// One or more modules failed to build. |
177 | bool DisableGeneratingGlobalModuleIndex = false; |
178 | |
179 | /// The stream for verbose output if owned, otherwise nullptr. |
180 | std::unique_ptr<raw_ostream> OwnedVerboseOutputStream; |
181 | |
182 | /// The stream for verbose output. |
183 | raw_ostream *VerboseOutputStream = &llvm::errs(); |
184 | |
185 | /// Holds information about the output file. |
186 | /// |
187 | /// If TempFilename is not empty we must rename it to Filename at the end. |
188 | /// TempFilename may be empty and Filename non-empty if creating the temporary |
189 | /// failed. |
190 | struct OutputFile { |
191 | std::string Filename; |
192 | std::optional<llvm::sys::fs::TempFile> File; |
193 | |
194 | OutputFile(std::string filename, |
195 | std::optional<llvm::sys::fs::TempFile> file) |
196 | : Filename(std::move(filename)), File(std::move(file)) {} |
197 | }; |
198 | |
199 | /// The list of active output files. |
200 | std::list<OutputFile> OutputFiles; |
201 | |
202 | /// Force an output buffer. |
203 | std::unique_ptr<llvm::raw_pwrite_stream> OutputStream; |
204 | |
205 | CompilerInstance(const CompilerInstance &) = delete; |
206 | void operator=(const CompilerInstance &) = delete; |
207 | public: |
208 | explicit CompilerInstance( |
209 | std::shared_ptr<PCHContainerOperations> PCHContainerOps = |
210 | std::make_shared<PCHContainerOperations>(), |
211 | InMemoryModuleCache *SharedModuleCache = nullptr); |
212 | ~CompilerInstance() override; |
213 | |
214 | /// @name High-Level Operations |
215 | /// @{ |
216 | |
217 | /// ExecuteAction - Execute the provided action against the compiler's |
218 | /// CompilerInvocation object. |
219 | /// |
220 | /// This function makes the following assumptions: |
221 | /// |
222 | /// - The invocation options should be initialized. This function does not |
223 | /// handle the '-help' or '-version' options, clients should handle those |
224 | /// directly. |
225 | /// |
226 | /// - The diagnostics engine should have already been created by the client. |
227 | /// |
228 | /// - No other CompilerInstance state should have been initialized (this is |
229 | /// an unchecked error). |
230 | /// |
231 | /// - Clients should have initialized any LLVM target features that may be |
232 | /// required. |
233 | /// |
234 | /// - Clients should eventually call llvm_shutdown() upon the completion of |
235 | /// this routine to ensure that any managed objects are properly destroyed. |
236 | /// |
237 | /// Note that this routine may write output to 'stderr'. |
238 | /// |
239 | /// \param Act - The action to execute. |
240 | /// \return - True on success. |
241 | // |
242 | // FIXME: Eliminate the llvm_shutdown requirement, that should either be part |
243 | // of the context or else not CompilerInstance specific. |
244 | bool ExecuteAction(FrontendAction &Act); |
245 | |
246 | /// At the end of a compilation, print the number of warnings/errors. |
247 | void printDiagnosticStats(); |
248 | |
249 | /// Load the list of plugins requested in the \c FrontendOptions. |
250 | void LoadRequestedPlugins(); |
251 | |
252 | /// @} |
253 | /// @name Compiler Invocation and Options |
254 | /// @{ |
255 | |
256 | bool hasInvocation() const { return Invocation != nullptr; } |
257 | |
258 | CompilerInvocation &getInvocation() { |
259 | assert(Invocation && "Compiler instance has no invocation!" ); |
260 | return *Invocation; |
261 | } |
262 | |
263 | std::shared_ptr<CompilerInvocation> getInvocationPtr() { return Invocation; } |
264 | |
265 | /// setInvocation - Replace the current invocation. |
266 | void setInvocation(std::shared_ptr<CompilerInvocation> Value); |
267 | |
268 | /// Indicates whether we should (re)build the global module index. |
269 | bool shouldBuildGlobalModuleIndex() const; |
270 | |
271 | /// Set the flag indicating whether we should (re)build the global |
272 | /// module index. |
273 | void setBuildGlobalModuleIndex(bool Build) { |
274 | BuildGlobalModuleIndex = Build; |
275 | } |
276 | |
277 | /// @} |
278 | /// @name Forwarding Methods |
279 | /// @{ |
280 | |
281 | AnalyzerOptions &getAnalyzerOpts() { return Invocation->getAnalyzerOpts(); } |
282 | |
283 | CodeGenOptions &getCodeGenOpts() { |
284 | return Invocation->getCodeGenOpts(); |
285 | } |
286 | const CodeGenOptions &getCodeGenOpts() const { |
287 | return Invocation->getCodeGenOpts(); |
288 | } |
289 | |
290 | DependencyOutputOptions &getDependencyOutputOpts() { |
291 | return Invocation->getDependencyOutputOpts(); |
292 | } |
293 | const DependencyOutputOptions &getDependencyOutputOpts() const { |
294 | return Invocation->getDependencyOutputOpts(); |
295 | } |
296 | |
297 | DiagnosticOptions &getDiagnosticOpts() { |
298 | return Invocation->getDiagnosticOpts(); |
299 | } |
300 | const DiagnosticOptions &getDiagnosticOpts() const { |
301 | return Invocation->getDiagnosticOpts(); |
302 | } |
303 | |
304 | FileSystemOptions &getFileSystemOpts() { |
305 | return Invocation->getFileSystemOpts(); |
306 | } |
307 | const FileSystemOptions &getFileSystemOpts() const { |
308 | return Invocation->getFileSystemOpts(); |
309 | } |
310 | |
311 | FrontendOptions &getFrontendOpts() { |
312 | return Invocation->getFrontendOpts(); |
313 | } |
314 | const FrontendOptions &getFrontendOpts() const { |
315 | return Invocation->getFrontendOpts(); |
316 | } |
317 | |
318 | HeaderSearchOptions &() { |
319 | return Invocation->getHeaderSearchOpts(); |
320 | } |
321 | const HeaderSearchOptions &() const { |
322 | return Invocation->getHeaderSearchOpts(); |
323 | } |
324 | std::shared_ptr<HeaderSearchOptions> () const { |
325 | return Invocation->getHeaderSearchOptsPtr(); |
326 | } |
327 | |
328 | APINotesOptions &getAPINotesOpts() { return Invocation->getAPINotesOpts(); } |
329 | const APINotesOptions &getAPINotesOpts() const { |
330 | return Invocation->getAPINotesOpts(); |
331 | } |
332 | |
333 | LangOptions &getLangOpts() { return Invocation->getLangOpts(); } |
334 | const LangOptions &getLangOpts() const { return Invocation->getLangOpts(); } |
335 | std::shared_ptr<LangOptions> getLangOptsPtr() const { |
336 | return Invocation->getLangOptsPtr(); |
337 | } |
338 | |
339 | PreprocessorOptions &getPreprocessorOpts() { |
340 | return Invocation->getPreprocessorOpts(); |
341 | } |
342 | const PreprocessorOptions &getPreprocessorOpts() const { |
343 | return Invocation->getPreprocessorOpts(); |
344 | } |
345 | |
346 | PreprocessorOutputOptions &getPreprocessorOutputOpts() { |
347 | return Invocation->getPreprocessorOutputOpts(); |
348 | } |
349 | const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { |
350 | return Invocation->getPreprocessorOutputOpts(); |
351 | } |
352 | |
353 | TargetOptions &getTargetOpts() { |
354 | return Invocation->getTargetOpts(); |
355 | } |
356 | const TargetOptions &getTargetOpts() const { |
357 | return Invocation->getTargetOpts(); |
358 | } |
359 | |
360 | /// @} |
361 | /// @name Diagnostics Engine |
362 | /// @{ |
363 | |
364 | bool hasDiagnostics() const { return Diagnostics != nullptr; } |
365 | |
366 | /// Get the current diagnostics engine. |
367 | DiagnosticsEngine &getDiagnostics() const { |
368 | assert(Diagnostics && "Compiler instance has no diagnostics!" ); |
369 | return *Diagnostics; |
370 | } |
371 | |
372 | IntrusiveRefCntPtr<DiagnosticsEngine> getDiagnosticsPtr() const { |
373 | assert(Diagnostics && "Compiler instance has no diagnostics!" ); |
374 | return Diagnostics; |
375 | } |
376 | |
377 | /// setDiagnostics - Replace the current diagnostics engine. |
378 | void setDiagnostics(DiagnosticsEngine *Value); |
379 | |
380 | DiagnosticConsumer &getDiagnosticClient() const { |
381 | assert(Diagnostics && Diagnostics->getClient() && |
382 | "Compiler instance has no diagnostic client!" ); |
383 | return *Diagnostics->getClient(); |
384 | } |
385 | |
386 | /// @} |
387 | /// @name VerboseOutputStream |
388 | /// @{ |
389 | |
390 | /// Replace the current stream for verbose output. |
391 | void setVerboseOutputStream(raw_ostream &Value); |
392 | |
393 | /// Replace the current stream for verbose output. |
394 | void setVerboseOutputStream(std::unique_ptr<raw_ostream> Value); |
395 | |
396 | /// Get the current stream for verbose output. |
397 | raw_ostream &getVerboseOutputStream() { |
398 | return *VerboseOutputStream; |
399 | } |
400 | |
401 | /// @} |
402 | /// @name Target Info |
403 | /// @{ |
404 | |
405 | bool hasTarget() const { return Target != nullptr; } |
406 | |
407 | TargetInfo &getTarget() const { |
408 | assert(Target && "Compiler instance has no target!" ); |
409 | return *Target; |
410 | } |
411 | |
412 | IntrusiveRefCntPtr<TargetInfo> getTargetPtr() const { |
413 | assert(Target && "Compiler instance has no target!" ); |
414 | return Target; |
415 | } |
416 | |
417 | /// Replace the current Target. |
418 | void setTarget(TargetInfo *Value); |
419 | |
420 | /// @} |
421 | /// @name AuxTarget Info |
422 | /// @{ |
423 | |
424 | TargetInfo *getAuxTarget() const { return AuxTarget.get(); } |
425 | |
426 | /// Replace the current AuxTarget. |
427 | void setAuxTarget(TargetInfo *Value); |
428 | |
429 | // Create Target and AuxTarget based on current options |
430 | bool createTarget(); |
431 | |
432 | /// @} |
433 | /// @name Virtual File System |
434 | /// @{ |
435 | |
436 | llvm::vfs::FileSystem &getVirtualFileSystem() const; |
437 | |
438 | /// @} |
439 | /// @name File Manager |
440 | /// @{ |
441 | |
442 | bool hasFileManager() const { return FileMgr != nullptr; } |
443 | |
444 | /// Return the current file manager to the caller. |
445 | FileManager &getFileManager() const { |
446 | assert(FileMgr && "Compiler instance has no file manager!" ); |
447 | return *FileMgr; |
448 | } |
449 | |
450 | IntrusiveRefCntPtr<FileManager> getFileManagerPtr() const { |
451 | assert(FileMgr && "Compiler instance has no file manager!" ); |
452 | return FileMgr; |
453 | } |
454 | |
455 | void resetAndLeakFileManager() { |
456 | llvm::BuryPointer(Ptr: FileMgr.get()); |
457 | FileMgr.resetWithoutRelease(); |
458 | } |
459 | |
460 | /// Replace the current file manager and virtual file system. |
461 | void setFileManager(FileManager *Value); |
462 | |
463 | /// @} |
464 | /// @name Source Manager |
465 | /// @{ |
466 | |
467 | bool hasSourceManager() const { return SourceMgr != nullptr; } |
468 | |
469 | /// Return the current source manager. |
470 | SourceManager &getSourceManager() const { |
471 | assert(SourceMgr && "Compiler instance has no source manager!" ); |
472 | return *SourceMgr; |
473 | } |
474 | |
475 | IntrusiveRefCntPtr<SourceManager> getSourceManagerPtr() const { |
476 | assert(SourceMgr && "Compiler instance has no source manager!" ); |
477 | return SourceMgr; |
478 | } |
479 | |
480 | void resetAndLeakSourceManager() { |
481 | llvm::BuryPointer(Ptr: SourceMgr.get()); |
482 | SourceMgr.resetWithoutRelease(); |
483 | } |
484 | |
485 | /// setSourceManager - Replace the current source manager. |
486 | void setSourceManager(SourceManager *Value); |
487 | |
488 | /// @} |
489 | /// @name Preprocessor |
490 | /// @{ |
491 | |
492 | bool hasPreprocessor() const { return PP != nullptr; } |
493 | |
494 | /// Return the current preprocessor. |
495 | Preprocessor &getPreprocessor() const { |
496 | assert(PP && "Compiler instance has no preprocessor!" ); |
497 | return *PP; |
498 | } |
499 | |
500 | std::shared_ptr<Preprocessor> getPreprocessorPtr() { return PP; } |
501 | |
502 | void resetAndLeakPreprocessor() { |
503 | llvm::BuryPointer(Ptr: new std::shared_ptr<Preprocessor>(PP)); |
504 | } |
505 | |
506 | /// Replace the current preprocessor. |
507 | void setPreprocessor(std::shared_ptr<Preprocessor> Value); |
508 | |
509 | /// @} |
510 | /// @name ASTContext |
511 | /// @{ |
512 | |
513 | bool hasASTContext() const { return Context != nullptr; } |
514 | |
515 | ASTContext &getASTContext() const { |
516 | assert(Context && "Compiler instance has no AST context!" ); |
517 | return *Context; |
518 | } |
519 | |
520 | IntrusiveRefCntPtr<ASTContext> getASTContextPtr() const { |
521 | assert(Context && "Compiler instance has no AST context!" ); |
522 | return Context; |
523 | } |
524 | |
525 | void resetAndLeakASTContext() { |
526 | llvm::BuryPointer(Ptr: Context.get()); |
527 | Context.resetWithoutRelease(); |
528 | } |
529 | |
530 | /// setASTContext - Replace the current AST context. |
531 | void setASTContext(ASTContext *Value); |
532 | |
533 | /// Replace the current Sema; the compiler instance takes ownership |
534 | /// of S. |
535 | void setSema(Sema *S); |
536 | |
537 | /// @} |
538 | /// @name ASTConsumer |
539 | /// @{ |
540 | |
541 | bool hasASTConsumer() const { return (bool)Consumer; } |
542 | |
543 | ASTConsumer &getASTConsumer() const { |
544 | assert(Consumer && "Compiler instance has no AST consumer!" ); |
545 | return *Consumer; |
546 | } |
547 | |
548 | /// takeASTConsumer - Remove the current AST consumer and give ownership to |
549 | /// the caller. |
550 | std::unique_ptr<ASTConsumer> takeASTConsumer() { return std::move(Consumer); } |
551 | |
552 | /// setASTConsumer - Replace the current AST consumer; the compiler instance |
553 | /// takes ownership of \p Value. |
554 | void setASTConsumer(std::unique_ptr<ASTConsumer> Value); |
555 | |
556 | /// @} |
557 | /// @name Semantic analysis |
558 | /// @{ |
559 | bool hasSema() const { return (bool)TheSema; } |
560 | |
561 | Sema &getSema() const { |
562 | assert(TheSema && "Compiler instance has no Sema object!" ); |
563 | return *TheSema; |
564 | } |
565 | |
566 | std::unique_ptr<Sema> takeSema(); |
567 | void resetAndLeakSema(); |
568 | |
569 | /// @} |
570 | /// @name Module Management |
571 | /// @{ |
572 | |
573 | IntrusiveRefCntPtr<ASTReader> getASTReader() const; |
574 | void setASTReader(IntrusiveRefCntPtr<ASTReader> Reader); |
575 | |
576 | std::shared_ptr<ModuleDependencyCollector> getModuleDepCollector() const; |
577 | void setModuleDepCollector( |
578 | std::shared_ptr<ModuleDependencyCollector> Collector); |
579 | |
580 | std::shared_ptr<PCHContainerOperations> getPCHContainerOperations() const { |
581 | return ThePCHContainerOperations; |
582 | } |
583 | |
584 | /// Return the appropriate PCHContainerWriter depending on the |
585 | /// current CodeGenOptions. |
586 | const PCHContainerWriter &getPCHContainerWriter() const { |
587 | assert(Invocation && "cannot determine module format without invocation" ); |
588 | StringRef Format = getHeaderSearchOpts().ModuleFormat; |
589 | auto *Writer = ThePCHContainerOperations->getWriterOrNull(Format); |
590 | if (!Writer) { |
591 | if (Diagnostics) |
592 | Diagnostics->Report(diag::err_module_format_unhandled) << Format; |
593 | llvm::report_fatal_error(reason: "unknown module format" ); |
594 | } |
595 | return *Writer; |
596 | } |
597 | |
598 | /// Return the appropriate PCHContainerReader depending on the |
599 | /// current CodeGenOptions. |
600 | const PCHContainerReader &getPCHContainerReader() const { |
601 | assert(Invocation && "cannot determine module format without invocation" ); |
602 | StringRef Format = getHeaderSearchOpts().ModuleFormat; |
603 | auto *Reader = ThePCHContainerOperations->getReaderOrNull(Format); |
604 | if (!Reader) { |
605 | if (Diagnostics) |
606 | Diagnostics->Report(diag::err_module_format_unhandled) << Format; |
607 | llvm::report_fatal_error(reason: "unknown module format" ); |
608 | } |
609 | return *Reader; |
610 | } |
611 | |
612 | /// @} |
613 | /// @name Code Completion |
614 | /// @{ |
615 | |
616 | bool hasCodeCompletionConsumer() const { return (bool)CompletionConsumer; } |
617 | |
618 | CodeCompleteConsumer &getCodeCompletionConsumer() const { |
619 | assert(CompletionConsumer && |
620 | "Compiler instance has no code completion consumer!" ); |
621 | return *CompletionConsumer; |
622 | } |
623 | |
624 | /// setCodeCompletionConsumer - Replace the current code completion consumer; |
625 | /// the compiler instance takes ownership of \p Value. |
626 | void setCodeCompletionConsumer(CodeCompleteConsumer *Value); |
627 | |
628 | /// @} |
629 | /// @name Frontend timer |
630 | /// @{ |
631 | |
632 | bool hasFrontendTimer() const { return (bool)FrontendTimer; } |
633 | |
634 | llvm::Timer &getFrontendTimer() const { |
635 | assert(FrontendTimer && "Compiler instance has no frontend timer!" ); |
636 | return *FrontendTimer; |
637 | } |
638 | |
639 | /// @} |
640 | /// @name Failed modules set |
641 | /// @{ |
642 | |
643 | bool hasFailedModulesSet() const { return (bool)FailedModules; } |
644 | |
645 | void createFailedModulesSet() { |
646 | FailedModules = std::make_shared<FailedModulesSet>(); |
647 | } |
648 | |
649 | std::shared_ptr<FailedModulesSet> getFailedModulesSetPtr() const { |
650 | return FailedModules; |
651 | } |
652 | |
653 | void setFailedModulesSet(std::shared_ptr<FailedModulesSet> FMS) { |
654 | FailedModules = FMS; |
655 | } |
656 | |
657 | /// } |
658 | /// @name Output Files |
659 | /// @{ |
660 | |
661 | /// clearOutputFiles - Clear the output file list. The underlying output |
662 | /// streams must have been closed beforehand. |
663 | /// |
664 | /// \param EraseFiles - If true, attempt to erase the files from disk. |
665 | void clearOutputFiles(bool EraseFiles); |
666 | |
667 | /// @} |
668 | /// @name Construction Utility Methods |
669 | /// @{ |
670 | |
671 | /// Create the diagnostics engine using the invocation's diagnostic options |
672 | /// and replace any existing one with it. |
673 | /// |
674 | /// Note that this routine also replaces the diagnostic client, |
675 | /// allocating one if one is not provided. |
676 | /// |
677 | /// \param Client If non-NULL, a diagnostic client that will be |
678 | /// attached to (and, then, owned by) the DiagnosticsEngine inside this AST |
679 | /// unit. |
680 | /// |
681 | /// \param ShouldOwnClient If Client is non-NULL, specifies whether |
682 | /// the diagnostic object should take ownership of the client. |
683 | void createDiagnostics(DiagnosticConsumer *Client = nullptr, |
684 | bool ShouldOwnClient = true); |
685 | |
686 | /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter. |
687 | /// |
688 | /// If no diagnostic client is provided, this creates a |
689 | /// DiagnosticConsumer that is owned by the returned diagnostic |
690 | /// object, if using directly the caller is responsible for |
691 | /// releasing the returned DiagnosticsEngine's client eventually. |
692 | /// |
693 | /// \param Opts - The diagnostic options; note that the created text |
694 | /// diagnostic object contains a reference to these options. |
695 | /// |
696 | /// \param Client If non-NULL, a diagnostic client that will be |
697 | /// attached to (and, then, owned by) the returned DiagnosticsEngine |
698 | /// object. |
699 | /// |
700 | /// \param CodeGenOpts If non-NULL, the code gen options in use, which may be |
701 | /// used by some diagnostics printers (for logging purposes only). |
702 | /// |
703 | /// \return The new object on success, or null on failure. |
704 | static IntrusiveRefCntPtr<DiagnosticsEngine> |
705 | createDiagnostics(DiagnosticOptions *Opts, |
706 | DiagnosticConsumer *Client = nullptr, |
707 | bool ShouldOwnClient = true, |
708 | const CodeGenOptions *CodeGenOpts = nullptr); |
709 | |
710 | /// Create the file manager and replace any existing one with it. |
711 | /// |
712 | /// \return The new file manager on success, or null on failure. |
713 | FileManager * |
714 | createFileManager(IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr); |
715 | |
716 | /// Create the source manager and replace any existing one with it. |
717 | void createSourceManager(FileManager &FileMgr); |
718 | |
719 | /// Create the preprocessor, using the invocation, file, and source managers, |
720 | /// and replace any existing one with it. |
721 | void createPreprocessor(TranslationUnitKind TUKind); |
722 | |
723 | std::string getSpecificModuleCachePath(StringRef ModuleHash); |
724 | std::string getSpecificModuleCachePath() { |
725 | return getSpecificModuleCachePath(ModuleHash: getInvocation().getModuleHash()); |
726 | } |
727 | |
728 | /// Create the AST context. |
729 | void createASTContext(); |
730 | |
731 | /// Create an external AST source to read a PCH file and attach it to the AST |
732 | /// context. |
733 | void createPCHExternalASTSource( |
734 | StringRef Path, DisableValidationForModuleKind DisableValidation, |
735 | bool AllowPCHWithCompilerErrors, void *DeserializationListener, |
736 | bool OwnDeserializationListener); |
737 | |
738 | /// Create an external AST source to read a PCH file. |
739 | /// |
740 | /// \return - The new object on success, or null on failure. |
741 | static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource( |
742 | StringRef Path, StringRef Sysroot, |
743 | DisableValidationForModuleKind DisableValidation, |
744 | bool AllowPCHWithCompilerErrors, Preprocessor &PP, |
745 | InMemoryModuleCache &ModuleCache, ASTContext &Context, |
746 | const PCHContainerReader &PCHContainerRdr, |
747 | ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, |
748 | ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors, |
749 | void *DeserializationListener, bool OwnDeserializationListener, |
750 | bool Preamble, bool UseGlobalModuleIndex); |
751 | |
752 | /// Create a code completion consumer using the invocation; note that this |
753 | /// will cause the source manager to truncate the input source file at the |
754 | /// completion point. |
755 | void createCodeCompletionConsumer(); |
756 | |
757 | /// Create a code completion consumer to print code completion results, at |
758 | /// \p Filename, \p Line, and \p Column, to the given output stream \p OS. |
759 | static CodeCompleteConsumer *createCodeCompletionConsumer( |
760 | Preprocessor &PP, StringRef Filename, unsigned Line, unsigned Column, |
761 | const CodeCompleteOptions &Opts, raw_ostream &OS); |
762 | |
763 | /// Create the Sema object to be used for parsing. |
764 | void createSema(TranslationUnitKind TUKind, |
765 | CodeCompleteConsumer *CompletionConsumer); |
766 | |
767 | /// Create the frontend timer and replace any existing one with it. |
768 | void createFrontendTimer(); |
769 | |
770 | /// Create the default output file (from the invocation's options) and add it |
771 | /// to the list of tracked output files. |
772 | /// |
773 | /// The files created by this are usually removed on signal, and, depending |
774 | /// on FrontendOptions, may also use a temporary file (that is, the data is |
775 | /// written to a temporary file which will atomically replace the target |
776 | /// output on success). |
777 | /// |
778 | /// \return - Null on error. |
779 | std::unique_ptr<raw_pwrite_stream> createDefaultOutputFile( |
780 | bool Binary = true, StringRef BaseInput = "" , StringRef Extension = "" , |
781 | bool RemoveFileOnSignal = true, bool CreateMissingDirectories = false, |
782 | bool ForceUseTemporary = false); |
783 | |
784 | /// Create a new output file, optionally deriving the output path name, and |
785 | /// add it to the list of tracked output files. |
786 | /// |
787 | /// \return - Null on error. |
788 | std::unique_ptr<raw_pwrite_stream> |
789 | createOutputFile(StringRef OutputPath, bool Binary, bool RemoveFileOnSignal, |
790 | bool UseTemporary, bool CreateMissingDirectories = false); |
791 | |
792 | private: |
793 | /// Create a new output file and add it to the list of tracked output files. |
794 | /// |
795 | /// If \p OutputPath is empty, then createOutputFile will derive an output |
796 | /// path location as \p BaseInput, with any suffix removed, and \p Extension |
797 | /// appended. If \p OutputPath is not stdout and \p UseTemporary |
798 | /// is true, createOutputFile will create a new temporary file that must be |
799 | /// renamed to \p OutputPath in the end. |
800 | /// |
801 | /// \param OutputPath - If given, the path to the output file. |
802 | /// \param Binary - The mode to open the file in. |
803 | /// \param RemoveFileOnSignal - Whether the file should be registered with |
804 | /// llvm::sys::RemoveFileOnSignal. Note that this is not safe for |
805 | /// multithreaded use, as the underlying signal mechanism is not reentrant |
806 | /// \param UseTemporary - Create a new temporary file that must be renamed to |
807 | /// OutputPath in the end. |
808 | /// \param CreateMissingDirectories - When \p UseTemporary is true, create |
809 | /// missing directories in the output path. |
810 | Expected<std::unique_ptr<raw_pwrite_stream>> |
811 | createOutputFileImpl(StringRef OutputPath, bool Binary, |
812 | bool RemoveFileOnSignal, bool UseTemporary, |
813 | bool CreateMissingDirectories); |
814 | |
815 | public: |
816 | std::unique_ptr<raw_pwrite_stream> createNullOutputFile(); |
817 | |
818 | /// @} |
819 | /// @name Initialization Utility Methods |
820 | /// @{ |
821 | |
822 | /// InitializeSourceManager - Initialize the source manager to set InputFile |
823 | /// as the main file. |
824 | /// |
825 | /// \return True on success. |
826 | bool InitializeSourceManager(const FrontendInputFile &Input); |
827 | |
828 | /// InitializeSourceManager - Initialize the source manager to set InputFile |
829 | /// as the main file. |
830 | /// |
831 | /// \return True on success. |
832 | static bool InitializeSourceManager(const FrontendInputFile &Input, |
833 | DiagnosticsEngine &Diags, |
834 | FileManager &FileMgr, |
835 | SourceManager &SourceMgr); |
836 | |
837 | /// @} |
838 | |
839 | void setOutputStream(std::unique_ptr<llvm::raw_pwrite_stream> OutStream) { |
840 | OutputStream = std::move(OutStream); |
841 | } |
842 | |
843 | std::unique_ptr<llvm::raw_pwrite_stream> takeOutputStream() { |
844 | return std::move(OutputStream); |
845 | } |
846 | |
847 | void createASTReader(); |
848 | |
849 | bool loadModuleFile(StringRef FileName, |
850 | serialization::ModuleFile *&LoadedModuleFile); |
851 | |
852 | private: |
853 | /// Find a module, potentially compiling it, before reading its AST. This is |
854 | /// the guts of loadModule. |
855 | /// |
856 | /// For prebuilt modules, the Module is not expected to exist in |
857 | /// HeaderSearch's ModuleMap. If a ModuleFile by that name is in the |
858 | /// ModuleManager, then it will be loaded and looked up. |
859 | /// |
860 | /// For implicit modules, the Module is expected to already be in the |
861 | /// ModuleMap. First attempt to load it from the given path on disk. If that |
862 | /// fails, defer to compileModuleAndReadAST, which will first build and then |
863 | /// load it. |
864 | ModuleLoadResult findOrCompileModuleAndReadAST(StringRef ModuleName, |
865 | SourceLocation ImportLoc, |
866 | SourceLocation ModuleNameLoc, |
867 | bool IsInclusionDirective); |
868 | |
869 | public: |
870 | ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, |
871 | Module::NameVisibilityKind Visibility, |
872 | bool IsInclusionDirective) override; |
873 | |
874 | void createModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName, |
875 | StringRef Source) override; |
876 | |
877 | void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility, |
878 | SourceLocation ImportLoc) override; |
879 | |
880 | bool hadModuleLoaderFatalFailure() const { |
881 | return ModuleLoader::HadFatalFailure; |
882 | } |
883 | |
884 | GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override; |
885 | |
886 | bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override; |
887 | |
888 | void addDependencyCollector(std::shared_ptr<DependencyCollector> Listener) { |
889 | DependencyCollectors.push_back(x: std::move(Listener)); |
890 | } |
891 | |
892 | void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS); |
893 | |
894 | InMemoryModuleCache &getModuleCache() const { return *ModuleCache; } |
895 | }; |
896 | |
897 | } // end namespace clang |
898 | |
899 | #endif |
900 | |