clang: lib/Frontend/PrecompiledPreamble.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
25#include "llvm/ADT/SmallString.h"
26#include "llvm/ADT/StringSet.h"
27#include "llvm/ADT/iterator_range.h"
28#include "llvm/Config/llvm-config.h"
29#include "llvm/Support/CrashRecoveryContext.h"
30#include "llvm/Support/FileSystem.h"
31#include "llvm/Support/ManagedStatic.h"
32#include "llvm/Support/Path.h"
33#include "llvm/Support/Process.h"
34#include "llvm/Support/VirtualFileSystem.h"
35#include
36#include
37#include
38
39using namespace clang;
40
41namespace {
42
43StringRef getInMemoryPreamblePath() {
44#if defined(LLVM_ON_UNIX)
45 return "/__clang_tmp/___clang_inmemory_preamble___";
46#elif defined(_WIN32)
47 return "C:\\__clang_tmp\\___clang_inmemory_preamble___";
48#else
49#warning "Unknown platform. Defaulting to UNIX-style paths for in-memory PCHs"
50 return "/__clang_tmp/___clang_inmemory_preamble___";
51#endif
52}
53
55createVFSOverlayForPreamblePCH(StringRef PCHFilename,
56 std::unique_ptrllvm::MemoryBuffer PCHBuffer,
58
59
61 new llvm::vfs::InMemoryFileSystem());
62 PCHFS->addFile(PCHFilename, 0, std::move(PCHBuffer));
64 new llvm::vfs::OverlayFileSystem(VFS));
65 Overlay->pushOverlay(PCHFS);
66 return Overlay;
67}
68
70public:
71
72
73
74
75
77};
78
79
80
81
82
83
84
85
86
87
88class MissingFileCollector : public PPCallbacks {
89 llvm::StringSet<> &Out;
92
93public:
94 MissingFileCollector(llvm::StringSet<> &Out, const HeaderSearch &Search,
96 : Out(Out), Search(Search), SM(SM) {}
97
99 StringRef FileName, bool IsAngled,
102 StringRef RelativePath, const Module *SuggestedModule,
103 bool ModuleImported,
105
106
108 return;
109
110
111 if (llvm::sys::path::is_absolute(FileName)) {
113 return;
114 }
115
116
119 Buf = DE.getName();
120 llvm::sys::path::append(Buf, FileName);
121 llvm::sys::path::remove_dots(Buf, true);
122 Out.insert(Buf);
123 };
124
125 if (!IsAngled) {
127 SM.getFileEntryRefForID(SM.getFileID(IncludeTok.getLocation())))
128 if (IncludingFile->getDir())
129 NotFoundRelativeTo(IncludingFile->getDir());
130 }
131
132 for (const auto &Dir : llvm::make_range(
135
136 if (Dir.isNormalDir())
137 NotFoundRelativeTo(*Dir.getDirRef());
138 }
139 }
140};
141
142
143class TemporaryFiles {
144public:
145
146 static TemporaryFiles &getInstance();
147
148private:
149
150 TemporaryFiles() = default;
151
152 TemporaryFiles(const TemporaryFiles &) = delete;
153
154public:
155 ~TemporaryFiles();
156
157
158 void addFile(StringRef File);
159
160
161 void removeFile(StringRef File);
162
163private:
164 std::mutex Mutex;
165 llvm::StringSet<> Files;
166};
167
168TemporaryFiles &TemporaryFiles::getInstance() {
169 static TemporaryFiles Instance;
170 return Instance;
171}
172
173TemporaryFiles::~TemporaryFiles() {
174 std::lock_guardstd::mutex Guard(Mutex);
175 for (const auto &File : Files)
176 llvm::sys::fs::remove(File.getKey());
177}
178
179void TemporaryFiles::addFile(StringRef File) {
180 std::lock_guardstd::mutex Guard(Mutex);
181 auto IsInserted = Files.insert(File).second;
182 (void)IsInserted;
183 assert(IsInserted && "File has already been added");
184}
185
186void TemporaryFiles::removeFile(StringRef File) {
187 std::lock_guardstd::mutex Guard(Mutex);
188 auto WasPresent = Files.erase(File);
189 (void)WasPresent;
190 assert(WasPresent && "File was not tracked");
191 llvm::sys::fs::remove(File);
192}
193
194
195
196
197
198
199class TempPCHFile {
200public:
201
202 static std::unique_ptr create(StringRef StoragePath) {
203
204
205
206 if (const char *TmpFile = ::getenv("CINDEXTEST_PREAMBLE_FILE"))
207 return std::unique_ptr(new TempPCHFile(TmpFile));
208
210
211
212
213
214 int FD;
215 std::error_code EC;
216 if (StoragePath.empty())
217 EC = llvm::sys::fs::createTemporaryFile("preamble", "pch", FD, File);
218 else {
220
221 llvm::sys::path::append(TempPath, "preamble-%%%%%%.pch");
222 namespace fs = llvm::sys::fs;
223
224 EC = fs::createUniqueFile(TempPath, FD, File, fs::OF_None,
225 fs::owner_read | fs::owner_write);
226 }
227 if (EC)
228 return nullptr;
229
230 llvm::sys::Process::SafelyCloseFileDescriptor(FD);
231 return std::unique_ptr(new TempPCHFile(File.str().str()));
232 }
233
234 TempPCHFile &operator=(const TempPCHFile &) = delete;
235 TempPCHFile(const TempPCHFile &) = delete;
236 ~TempPCHFile() { TemporaryFiles::getInstance().removeFile(FilePath); };
237
238
239 llvm::StringRef getFilePath() const { return FilePath; };
240
241private:
242 TempPCHFile(std::string FilePath) : FilePath(std::move(FilePath)) {
243 TemporaryFiles::getInstance().addFile(this->FilePath);
244 }
245
246 std::string FilePath;
247};
248
250public:
251 PrecompilePreambleAction(std::shared_ptr Buffer, bool WritePCHFile,
253 : Buffer(std::move(Buffer)), WritePCHFile(WritePCHFile),
254 Callbacks(Callbacks) {}
255
257 StringRef InFile) override;
258
259 bool hasEmittedPreamblePCH() const { return HasEmittedPreamblePCH; }
260
261 void setEmittedPreamblePCH(ASTWriter &Writer) {
262 if (FileOS) {
263 *FileOS << Buffer->Data;
264
265 FileOS.reset();
266 }
267
268 this->HasEmittedPreamblePCH = true;
269 Callbacks.AfterPCHEmitted(Writer);
270 }
271
275 }
276
281
282private:
283 friend class PrecompilePreambleConsumer;
284
285 bool HasEmittedPreamblePCH = false;
286 std::shared_ptr Buffer;
287 bool WritePCHFile;
288 std::unique_ptrllvm::raw\_pwrite\_stream FileOS;
290};
291
292class PrecompilePreambleConsumer : public PCHGenerator {
293public:
294 PrecompilePreambleConsumer(PrecompilePreambleAction &Action, Preprocessor &PP,
296 StringRef isysroot,
297 std::shared_ptr Buffer)
298 : PCHGenerator(PP, ModuleCache, "", isysroot, std::move(Buffer),
300 true),
301 Action(Action) {}
302
304 Action.Callbacks.HandleTopLevelDecl(DG);
305 return true;
306 }
307
311 return;
312 Action.setEmittedPreamblePCH(getWriter());
313 }
314
316 return Action.Callbacks.shouldSkipFunctionBody(D);
317 }
318
319private:
320 PrecompilePreambleAction &Action;
321};
322
323std::unique_ptr
324PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
325 StringRef InFile) {
326 std::string Sysroot;
328 return nullptr;
329
330 if (WritePCHFile) {
331 std::string OutputFile;
333 if (!FileOS)
334 return nullptr;
335 }
336
338 Sysroot.clear();
339
340 return std::make_unique(
342}
343
344template bool moveOnNoError(llvm::ErrorOr Val, T &Output) {
345 if (!Val)
346 return false;
347 Output = std::move(*Val);
348 return true;
349}
350
351}
352
354 const llvm::MemoryBufferRef &Buffer,
355 unsigned MaxLines) {
357}
358
360public:
361 static std::unique_ptr file(std::unique_ptr File) {
362 assert(File);
363 std::unique_ptr S(new PCHStorage());
364 S->File = std::move(File);
365 return S;
366 }
367 static std::unique_ptr inMemory(std::shared_ptr Buf) {
368 std::unique_ptr S(new PCHStorage());
369 S->Memory = std::move(Buf);
370 return S;
371 }
372
373 enum class Kind { InMemory, TempFile };
375 if (Memory)
376 return Kind::InMemory;
378 return Kind::TempFile;
379 llvm_unreachable("Neither Memory nor File?");
380 }
382 assert(getKind() == Kind::TempFile);
383 return File->getFilePath();
384 }
386 assert(getKind() == Kind::InMemory);
387 return StringRef(Memory->Data.data(), Memory->Data.size());
388 }
389
390
391
392
394 if (!Memory)
395 return;
396 Memory->Data = decltype(Memory->Data)(Memory->Data);
397 }
398
399private:
403
404 std::shared_ptr Memory;
405 std::unique_ptr File;
406};
407
412
415 const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
418 std::shared_ptr PCHContainerOps, bool StoreInMemory,
420 assert(VFS && "VFS is null");
421
422 auto PreambleInvocation = std::make_shared(Invocation);
423 FrontendOptions &FrontendOpts = PreambleInvocation->getFrontendOpts();
425 PreambleInvocation->getPreprocessorOpts();
426
427 std::shared_ptr Buffer = std::make_shared();
428 std::unique_ptr Storage;
429 if (StoreInMemory) {
431 } else {
432
433
434 std::unique_ptr PreamblePCHFile =
435 TempPCHFile::create(StoragePath);
436 if (!PreamblePCHFile)
439 }
440
441
442
443 std::vector PreambleBytes(MainFileBuffer->getBufferStart(),
444 MainFileBuffer->getBufferStart() +
445 Bounds.Size);
447
448
450 FrontendOpts.OutputFile = std::string(
451 StoreInMemory ? getInMemoryPreamblePath() : Storage->filePath());
454
456
457
458 std::unique_ptr Clang(
460
461
462 llvm::CrashRecoveryContextCleanupRegistrar CICleanup(
463 Clang.get());
464
465 Clang->setInvocation(std::move(PreambleInvocation));
466 Clang->setDiagnostics(&Diagnostics);
467
468
469 if (!Clang->createTarget())
471
472 if (Clang->getFrontendOpts().Inputs.size() != 1 ||
473 Clang->getFrontendOpts().Inputs[0].getKind().getFormat() !=
475 Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() ==
478 }
479
480
481 Diagnostics.Reset();
483
484 VFS =
486
487
488 Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS));
489
490
491 Clang->setSourceManager(
492 new SourceManager(Diagnostics, Clang->getFileManager()));
493
494 auto PreambleDepCollector = std::make_shared();
495 Clang->addDependencyCollector(PreambleDepCollector);
496
497 Clang->getLangOpts().CompilingPCH = true;
498
499
500 StringRef MainFilePath = FrontendOpts.Inputs[0].getFile();
501 auto PreambleInputBuffer = llvm::MemoryBuffer::getMemBufferCopy(
502 MainFileBuffer->getBuffer().slice(0, Bounds.Size), MainFilePath);
504
505 PreprocessorOpts.addRemappedFile(MainFilePath, PreambleInputBuffer.get());
506 } else {
507
508
510 PreambleInputBuffer.release());
511 }
512
513 auto Act = std::make_unique(
514 std::move(Buffer),
515 Storage->getKind() == PCHStorage::Kind::TempFile,
516 Callbacks);
517 if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
519
520
521
523
524 std::unique_ptr DelegatedPPCallbacks =
526 if (DelegatedPPCallbacks)
527 Clang->getPreprocessor().addPPCallbacks(std::move(DelegatedPPCallbacks));
529 Clang->getPreprocessor().addCommentHandler(CommentHandler);
530 llvm::StringSet<> MissingFiles;
531 Clang->getPreprocessor().addPPCallbacks(
532 std::make_unique(
533 MissingFiles, Clang->getPreprocessor().getHeaderSearchInfo(),
534 Clang->getSourceManager()));
535
536 if (llvm::Error Err = Act->Execute())
537 return errorToErrorCode(std::move(Err));
538
539
541
542 Act->EndSourceFile();
543
544 if (!Act->hasEmittedPreamblePCH())
546 Act.reset();
547
548
549
550 llvm::StringMapPrecompiledPreamble::PreambleFileHash FilesInPreamble;
551
552 SourceManager &SourceMgr = Clang->getSourceManager();
553 for (auto &Filename : PreambleDepCollector->getDependencies()) {
555 if (!MaybeFile ||
557 continue;
558 auto File = *MaybeFile;
559 if (time_t ModTime = File.getModificationTime()) {
560 FilesInPreamble[File.getName()] =
561 PrecompiledPreamble::PreambleFileHash::createForFile(File.getSize(),
562 ModTime);
563 } else {
564 llvm::MemoryBufferRef Buffer =
566 FilesInPreamble[File.getName()] =
567 PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(Buffer);
568 }
569 }
570
571
572
573 CICleanup.unregister();
574 Clang.reset();
575 Storage->shrink();
577 std::move(Storage), std::move(PreambleBytes), PreambleEndsAtStartOfLine,
578 std::move(FilesInPreamble), std::move(MissingFiles));
579}
580
582 return PreambleBounds(PreambleBytes.size(), PreambleEndsAtStartOfLine);
583}
584
586 switch (Storage->getKind()) {
587 case PCHStorage::Kind::InMemory:
588 return Storage->memoryContents().size();
589 case PCHStorage::Kind::TempFile: {
591 if (llvm::sys::fs::file_size(Storage->filePath(), Result))
592 return 0;
593
594 assert(Result <= std::numeric_limitsstd::size\_t::max() &&
595 "file size did not fit into size_t");
597 }
598 }
599 llvm_unreachable("Unhandled storage kind");
600}
601
603 const llvm::MemoryBufferRef &MainFileBuffer,
605 llvm::vfs::FileSystem &VFS) const {
606
607 assert(
608 Bounds.Size <= MainFileBuffer.getBufferSize() &&
609 "Buffer is too large. Bounds were calculated from a different buffer?");
610
611 auto PreambleInvocation = std::make_shared(Invocation);
613 PreambleInvocation->getPreprocessorOpts();
614
615
616
617
618
619 if (PreambleBytes.size() != Bounds.Size ||
621 !std::equal(PreambleBytes.begin(), PreambleBytes.end(),
622 MainFileBuffer.getBuffer().begin()))
623 return false;
624
625
626
627
628
629
630 std::map<llvm::sys::fs::UniqueID, PreambleFileHash> OverriddenFiles;
631 llvm::StringSet<> OverriddenAbsPaths;
632 for (const auto &R : PreprocessorOpts.RemappedFiles) {
633 llvm::vfs::Status Status;
634 if ((VFS.status(R.second), Status)) {
635
636
637 return false;
638 }
639
641 if (!VFS.makeAbsolute(MappedPath))
642 OverriddenAbsPaths.insert(MappedPath);
643
644 OverriddenFiles[Status.getUniqueID()] = PreambleFileHash::createForFile(
645 Status.getSize(), llvm::sys::toTimeT(Status.getLastModificationTime()));
646 }
647
648
649 llvm::StringMap OverridenFileBuffers;
651 const PrecompiledPreamble::PreambleFileHash PreambleHash =
652 PreambleFileHash::createForMemoryBuffer(RB.second->getMemBufferRef());
653 llvm::vfs::Status Status;
655 OverriddenFiles[Status.getUniqueID()] = PreambleHash;
656 else
657 OverridenFileBuffers[RB.first] = PreambleHash;
658
660 if (!VFS.makeAbsolute(MappedPath))
661 OverriddenAbsPaths.insert(MappedPath);
662 }
663
664
665 for (const auto &F : FilesInPreamble) {
666 auto OverridenFileBuffer = OverridenFileBuffers.find(F.first());
667 if (OverridenFileBuffer != OverridenFileBuffers.end()) {
668
669
670 if (OverridenFileBuffer->second != F.second)
671 return false;
672 continue;
673 }
674
675 llvm::vfs::Status Status;
676 if ((VFS.status(F.first()), Status)) {
677
678
679 return false;
680 }
681
682 std::map<llvm::sys::fs::UniqueID, PreambleFileHash>::iterator Overridden =
683 OverriddenFiles.find(Status.getUniqueID());
684 if (Overridden != OverriddenFiles.end()) {
685
686
687 if (Overridden->second != F.second)
688 return false;
689 continue;
690 }
691
692
693
694 if (Status.getSize() != uint64_t(F.second.Size) ||
695 llvm::sys::toTimeT(Status.getLastModificationTime()) !=
696 F.second.ModTime)
697 return false;
698 }
699 for (const auto &F : MissingFiles) {
700
701 if (OverriddenAbsPaths.count(F.getKey()))
702 return false;
703
704
705 if (auto Status = VFS.status(F.getKey())) {
706 if (Status->isRegularFile())
707 return false;
708 }
709 }
710 return true;
711}
712
715 llvm::MemoryBuffer *MainFileBuffer) const {
716 PreambleBounds Bounds(PreambleBytes.size(), PreambleEndsAtStartOfLine);
717 configurePreamble(Bounds, CI, VFS, MainFileBuffer);
718}
719
722 llvm::MemoryBuffer *MainFileBuffer) const {
724 configurePreamble(Bounds, CI, VFS, MainFileBuffer);
725}
726
728 std::unique_ptr Storage, std::vector PreambleBytes,
729 bool PreambleEndsAtStartOfLine,
730 llvm::StringMap FilesInPreamble,
731 llvm::StringSet<> MissingFiles)
732 : Storage(std::move(Storage)), FilesInPreamble(std::move(FilesInPreamble)),
733 MissingFiles(std::move(MissingFiles)),
734 PreambleBytes(std::move(PreambleBytes)),
735 PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {
736 assert(this->Storage != nullptr);
737}
738
739PrecompiledPreamble::PreambleFileHash
740PrecompiledPreamble::PreambleFileHash::createForFile(off_t Size,
741 time_t ModTime) {
742 PreambleFileHash Result;
744 Result.ModTime = ModTime;
747}
748
749PrecompiledPreamble::PreambleFileHash
750PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(
751 const llvm::MemoryBufferRef &Buffer) {
752 PreambleFileHash Result;
753 Result.Size = Buffer.getBufferSize();
755
756 llvm::MD5 MD5Ctx;
757 MD5Ctx.update(Buffer.getBuffer().data());
758 MD5Ctx.final(Result.MD5);
759
761}
762
763void PrecompiledPreamble::configurePreamble(
766 llvm::MemoryBuffer *MainFileBuffer) const {
767 assert(VFS);
768
770
771
773 PreprocessorOpts.addRemappedFile(MainFilePath, MainFileBuffer);
774
775
776 PreprocessorOpts.PrecompiledPreambleBytes.first = Bounds.Size;
777 PreprocessorOpts.PrecompiledPreambleBytes.second =
779 PreprocessorOpts.DisablePCHOrModuleValidation =
781
782
783
784 PreprocessorOpts.UsePredefines = false;
785
786 setupPreambleStorage(*Storage, PreprocessorOpts, VFS);
787}
788
789void PrecompiledPreamble::setupPreambleStorage(
792 if (Storage.getKind() == PCHStorage::Kind::TempFile) {
793 llvm::StringRef PCHPath = Storage.filePath();
795
796
798 llvm::vfs::getRealFileSystem();
799 if (VFS == RealFS || VFS->exists(PCHPath))
800 return;
801 auto Buf = RealFS->getBufferForFile(PCHPath);
802 if (!Buf) {
803
804
805
806 return;
807 }
808
809
810
811 VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(*Buf), VFS);
812 } else {
813 assert(Storage.getKind() == PCHStorage::Kind::InMemory);
814
815
816 StringRef PCHPath = getInMemoryPreamblePath();
818
819 auto Buf = llvm::MemoryBuffer::getMemBuffer(
820 Storage.memoryContents(), PCHPath, false);
821 VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(Buf), VFS);
822 }
823}
824
830 return nullptr;
831}
833
835
838}
839
841 return "build-preamble.error";
842}
843
847 return "Could not create temporary file for PCH";
849 return "CreateTargetInfo() return null";
851 return "BeginSourceFile() return an error";
853 return "Could not emit PCH";
855 return "Command line arguments must contain exactly one source file";
856 }
857 llvm_unreachable("unexpected BuildPreambleError");
858}
static bool moveOnNoError(llvm::ErrorOr< T > Val, T &Output)
Defines the clang::FileManager interface and associated types.
llvm::MachO::FileType FileType
static llvm::ManagedStatic< BuildPreambleErrorCategory > BuildPreambleErrCategory
Defines the clang::Preprocessor interface.
llvm::StringRef memoryContents() const
static std::unique_ptr< PCHStorage > file(std::unique_ptr< TempPCHFile > File)
static std::unique_ptr< PCHStorage > inMemory(std::shared_ptr< PCHBuffer > Buf)
llvm::StringRef filePath() const
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
virtual bool shouldSkipFunctionBody(Decl *D)
This callback is called for each function if the Parser was initialized with SkipFunctionBodies set t...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Abstract base class to use for AST consumer-based frontend actions.
Writes an AST file containing the contents of a translation unit.
std::string message(int condition) const override
const char * name() const noexcept override
Represents a character-granular source range.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
InMemoryModuleCache & getModuleCache() const
Preprocessor & getPreprocessor() const
Return the current preprocessor.
FrontendOptions & getFrontendOpts()
LangOptions & getLangOpts()
Helper class for holding the data necessary to invoke the compiler.
PreprocessorOptions & getPreprocessorOpts()
LangOptions & getLangOpts()
Mutable getters.
FrontendOptions & getFrontendOpts()
Decl - This represents one declaration (or definition), e.g.
An interface for collecting the dependencies of a compilation.
virtual bool needSystemDependencies()
Return true if system files should be passed to sawDependency().
Concrete class used by the front-end to report problems and issues.
void Reset(bool soft=false)
Reset the state of the diagnostic object to its initial configuration.
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
Implements support for file system lookup, file system caching, and directory search management.
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
virtual bool shouldEraseOutputFiles()
Callback at the end of processing a single input, to determine if the output files should be erased o...
virtual std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile)=0
Create the AST consumer object for this action, if supported.
virtual bool hasASTFileSupport() const
Does this action support use with AST files?
virtual bool BeginSourceFileAction(CompilerInstance &CI)
Callback at the start of processing a single input.
virtual TranslationUnitKind getTranslationUnitKind()
For AST-based actions, the kind of translation unit we're handling.
virtual bool hasCodeCompletionSupport() const
Does this action support use with code completion?
FrontendOptions - Options for controlling the behavior of the frontend.
std::string OutputFile
The output file, if any.
unsigned RelocatablePCH
When generating PCH files, instruct the AST writer to create relocatable PCH files.
SmallVector< FrontendInputFile, 0 > Inputs
The input files and their types.
frontend::ActionKind ProgramAction
The frontend action to perform.
static std::unique_ptr< llvm::raw_pwrite_stream > CreateOutputFile(CompilerInstance &CI, StringRef InFile, std::string &OutputFile)
Creates file to write the PCH into and returns a stream to write it into.
static bool ComputeASTConsumerArguments(CompilerInstance &CI, std::string &Sysroot)
Compute the AST consumer arguments that will be used to create the PCHGenerator instance returned by ...
In-memory cache for modules.
Record the location of an inclusion directive, such as an #include or #import statement.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static PreambleBounds ComputePreamble(StringRef Buffer, const LangOptions &LangOpts, unsigned MaxLines=0)
Compute the preamble of the given file.
An abstract superclass that describes a custom extension to the module/precompiled header file format...
Describes a module or submodule.
AST and semantic-analysis consumer that generates a precompiled header from the parsed source code.
void HandleTranslationUnit(ASTContext &Ctx) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
bool hasEmittedPCH() const
This interface provides a way to observe the actions of the preprocessor as it does its thing.
A set of callbacks to gather useful information while building a preamble.
virtual void AfterPCHEmitted(ASTWriter &Writer)
Called after PCH has been emitted.
virtual void BeforeExecute(CompilerInstance &CI)
Called before FrontendAction::Execute.
virtual CommentHandler * getCommentHandler()
The returned CommentHandler will be added to the preprocessor if not null.
virtual void HandleTopLevelDecl(DeclGroupRef DG)
Called for each TopLevelDecl.
virtual std::unique_ptr< PPCallbacks > createPPCallbacks()
Creates wrapper class for PPCallbacks so we can also process information about includes that are insi...
virtual void AfterExecute(CompilerInstance &CI)
Called after FrontendAction::Execute(), but before FrontendAction::EndSourceFile().
A class holding a PCH and all information to check whether it is valid to reuse the PCH for the subse...
void OverridePreamble(CompilerInvocation &CI, IntrusiveRefCntPtr< llvm::vfs::FileSystem > &VFS, llvm::MemoryBuffer *MainFileBuffer) const
Configure CI to use this preamble.
PrecompiledPreamble & operator=(PrecompiledPreamble &&)
static llvm::ErrorOr< PrecompiledPreamble > Build(const CompilerInvocation &Invocation, const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::shared_ptr< PCHContainerOperations > PCHContainerOps, bool StoreInMemory, StringRef StoragePath, PreambleCallbacks &Callbacks)
Try to build PrecompiledPreamble for Invocation.
bool CanReuse(const CompilerInvocation &Invocation, const llvm::MemoryBufferRef &MainFileBuffer, PreambleBounds Bounds, llvm::vfs::FileSystem &VFS) const
Check whether PrecompiledPreamble can be reused for the new contents(MainFileBuffer) of the main file...
void AddImplicitPreamble(CompilerInvocation &CI, IntrusiveRefCntPtr< llvm::vfs::FileSystem > &VFS, llvm::MemoryBuffer *MainFileBuffer) const
Changes options inside CI to use PCH from this preamble.
std::size_t getSize() const
Returns the size, in bytes, that preamble takes on disk or in memory.
PreambleBounds getBounds() const
PreambleBounds used to build the preamble.
PrecompiledPreamble(PrecompiledPreamble &&)
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
std::vector< std::pair< std::string, std::string > > RemappedFiles
The set of file remappings, which take existing files on the system (the first part of each pair) and...
std::pair< unsigned, bool > PrecompiledPreambleBytes
If non-zero, the implicit PCH include is actually a precompiled preamble that covers this number of b...
bool RetainRemappedFileBuffers
Whether the compiler instance should retain (i.e., not free) the buffers associated with remapped fil...
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
void addRemappedFile(StringRef From, StringRef To)
bool GeneratePreamble
True indicates that a preamble is being generated.
std::vector< std::pair< std::string, llvm::MemoryBuffer * > > RemappedFileBuffers
The set of file-to-buffer remappings, which take existing files on the system (the first part of each...
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
FileManager & getFileManager() const
FileID getMainFileID() const
Returns the FileID of the main source file.
llvm::MemoryBufferRef getMemoryBufferForFileOrFake(FileEntryRef File)
Retrieve the memory buffer associated with the given file.
Token - This structure provides full information about a lexed token.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
@ GeneratePCH
Generate pre-compiled header.
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
The JSON file list parser is used to communicate input to InstallAPI.
std::error_code make_error_code(BuildPreambleError Error)
@ Result
The result type of a method or function.
IntrusiveRefCntPtr< llvm::vfs::FileSystem > createVFSFromCompilerInvocation(const CompilerInvocation &CI, DiagnosticsEngine &Diags)
void ProcessWarningOptions(DiagnosticsEngine &Diags, const DiagnosticOptions &Opts, llvm::vfs::FileSystem &VFS, bool ReportDiags=true)
ProcessWarningOptions - Initialize the diagnostic client and process the warning options specified on...
TranslationUnitKind
Describes the kind of translation unit being processed.
@ TU_Prefix
The translation unit is a prefix to a translation unit, and is not complete.
const FunctionProtoType * T
@ PCH
Disable validation for a precompiled header and the modules it depends on.
PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, const llvm::MemoryBufferRef &Buffer, unsigned MaxLines)
Runs lexer to compute suggested preamble bounds.
@ CouldntCreateTargetInfo
Describes the bounds (start, size) of the preamble and a flag required by PreprocessorOptions::Precom...
unsigned Size
Size of the preamble in bytes.
bool PreambleEndsAtStartOfLine
Whether the preamble ends at the start of a new line.