25 #include "llvm/ADT/StringExtras.h" 26 #include "llvm/ADT/StringSet.h" 27 #include "llvm/Config/llvm-config.h" 28 #include "llvm/Support/CrashRecoveryContext.h" 29 #include "llvm/Support/FileSystem.h" 30 #include "llvm/Support/Process.h" 31 #include "llvm/Support/VirtualFileSystem.h" 36 using namespace clang;
40 StringRef getInMemoryPreamblePath() {
41 #if defined(LLVM_ON_UNIX) 42 return "/__clang_tmp/___clang_inmemory_preamble___";
44 return "C:\\__clang_tmp\\___clang_inmemory_preamble___";
46 #warning "Unknown platform. Defaulting to UNIX-style paths for in-memory PCHs" 47 return "/__clang_tmp/___clang_inmemory_preamble___";
52 createVFSOverlayForPreamblePCH(StringRef PCHFilename,
53 std::unique_ptr<llvm::MemoryBuffer>
PCHBuffer,
58 new llvm::vfs::InMemoryFileSystem());
59 PCHFS->addFile(PCHFilename, 0, std::move(PCHBuffer));
61 new llvm::vfs::OverlayFileSystem(VFS));
62 Overlay->pushOverlay(PCHFS);
73 bool needSystemDependencies()
override {
return true; }
77 class TemporaryFiles {
80 static TemporaryFiles &getInstance();
84 TemporaryFiles() =
default;
86 TemporaryFiles(
const TemporaryFiles &) =
delete;
92 void addFile(StringRef File);
95 void removeFile(StringRef File);
99 llvm::StringSet<> Files;
102 TemporaryFiles &TemporaryFiles::getInstance() {
103 static TemporaryFiles Instance;
107 TemporaryFiles::~TemporaryFiles() {
108 std::lock_guard<std::mutex> Guard(Mutex);
109 for (
const auto &File : Files)
113 void TemporaryFiles::addFile(StringRef File) {
114 std::lock_guard<std::mutex> Guard(Mutex);
115 auto IsInserted = Files.insert(File).second;
117 assert(IsInserted &&
"File has already been added");
120 void TemporaryFiles::removeFile(StringRef File) {
121 std::lock_guard<std::mutex> Guard(Mutex);
122 auto WasPresent = Files.erase(File);
124 assert(WasPresent &&
"File was not tracked");
130 PrecompilePreambleAction(std::string *InMemStorage,
132 : InMemStorage(InMemStorage), Callbacks(Callbacks) {}
135 StringRef InFile)
override;
137 bool hasEmittedPreamblePCH()
const {
return HasEmittedPreamblePCH; }
139 void setEmittedPreamblePCH(
ASTWriter &Writer) {
140 this->HasEmittedPreamblePCH =
true;
141 Callbacks.AfterPCHEmitted(Writer);
144 bool shouldEraseOutputFiles()
override {
return !hasEmittedPreamblePCH(); }
145 bool hasCodeCompletionSupport()
const override {
return false; }
146 bool hasASTFileSupport()
const override {
return false; }
150 friend class PrecompilePreambleConsumer;
152 bool HasEmittedPreamblePCH =
false;
153 std::string *InMemStorage;
157 class PrecompilePreambleConsumer :
public PCHGenerator {
159 PrecompilePreambleConsumer(PrecompilePreambleAction &Action,
163 std::unique_ptr<raw_ostream> Out)
165 std::make_shared<PCHBuffer>(),
168 Action(Action), Out(
std::move(Out)) {}
171 Action.Callbacks.HandleTopLevelDecl(DG);
175 void HandleTranslationUnit(
ASTContext &Ctx)
override {
177 if (!hasEmittedPCH())
186 getPCH() = std::move(Empty);
188 Action.setEmittedPreamblePCH(getWriter());
192 PrecompilePreambleAction &Action;
193 std::unique_ptr<raw_ostream> Out;
196 std::unique_ptr<ASTConsumer>
203 std::unique_ptr<llvm::raw_ostream>
OS;
205 OS = std::make_unique<llvm::raw_string_ostream>(*InMemStorage);
207 std::string OutputFile;
216 return std::make_unique<PrecompilePreambleConsumer>(
220 template <
class T>
bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
223 Output = std::move(*Val);
230 llvm::MemoryBuffer *Buffer,
240 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
bool StoreInMemory,
242 assert(VFS &&
"VFS is null");
244 auto PreambleInvocation = std::make_shared<CompilerInvocation>(Invocation);
247 PreambleInvocation->getPreprocessorOpts();
250 if (!StoreInMemory) {
253 llvm::ErrorOr<PrecompiledPreamble::TempPCHFile> PreamblePCHFile =
254 PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile();
255 if (!PreamblePCHFile)
257 TempFile = std::move(*PreamblePCHFile);
260 PCHStorage Storage = StoreInMemory ? PCHStorage(InMemoryPreamble())
261 : PCHStorage(std::move(*TempFile));
265 std::vector<char> PreambleBytes(MainFileBuffer->getBufferStart(),
266 MainFileBuffer->getBufferStart() +
272 FrontendOpts.OutputFile = StoreInMemory ? getInMemoryPreamblePath()
273 : Storage.asFile().getFilePath();
280 std::unique_ptr<CompilerInstance> Clang(
284 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> CICleanup(
287 Clang->setInvocation(std::move(PreambleInvocation));
288 Clang->setDiagnostics(&Diagnostics);
292 Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
293 if (!Clang->hasTarget())
300 Clang->getTarget().adjust(Clang->getLangOpts());
302 if (Clang->getFrontendOpts().Inputs.size() != 1 ||
303 Clang->getFrontendOpts().Inputs[0].getKind().getFormat() !=
305 Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() ==
318 Clang->setFileManager(
new FileManager(Clang->getFileSystemOpts(), VFS));
321 Clang->setSourceManager(
324 auto PreambleDepCollector = std::make_shared<PreambleDependencyCollector>();
325 Clang->addDependencyCollector(PreambleDepCollector);
328 StringRef MainFilePath = FrontendOpts.Inputs[0].getFile();
329 auto PreambleInputBuffer = llvm::MemoryBuffer::getMemBufferCopy(
330 MainFileBuffer->getBuffer().slice(0, Bounds.
Size), MainFilePath);
333 PreprocessorOpts.
addRemappedFile(MainFilePath, PreambleInputBuffer.get());
338 PreambleInputBuffer.release());
341 std::unique_ptr<PrecompilePreambleAction> Act;
342 Act.reset(
new PrecompilePreambleAction(
343 StoreInMemory ? &Storage.asMemory().Data :
nullptr, Callbacks));
345 if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
348 std::unique_ptr<PPCallbacks> DelegatedPPCallbacks =
350 if (DelegatedPPCallbacks)
351 Clang->getPreprocessor().addPPCallbacks(std::move(DelegatedPPCallbacks));
356 return errorToErrorCode(std::move(Err));
361 Act->EndSourceFile();
363 if (!Act->hasEmittedPreamblePCH())
368 llvm::StringMap<PrecompiledPreamble::PreambleFileHash> FilesInPreamble;
371 for (
auto &
Filename : PreambleDepCollector->getDependencies()) {
376 auto File = *FileOrErr;
377 if (time_t ModTime = File->getModificationTime()) {
378 FilesInPreamble[File->getName()] =
379 PrecompiledPreamble::PreambleFileHash::createForFile(File->getSize(),
383 FilesInPreamble[File->getName()] =
384 PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(Buffer);
389 PreambleEndsAtStartOfLine,
390 std::move(FilesInPreamble));
394 return PreambleBounds(PreambleBytes.size(), PreambleEndsAtStartOfLine);
398 switch (Storage.getKind()) {
399 case PCHStorage::Kind::Empty:
400 assert(
false &&
"Calling getSize() on invalid PrecompiledPreamble. " 401 "Was it std::moved?");
403 case PCHStorage::Kind::InMemory:
404 return Storage.asMemory().Data.size();
405 case PCHStorage::Kind::TempFile: {
407 if (llvm::sys::fs::file_size(Storage.asFile().getFilePath(),
Result))
411 "file size did not fit into size_t");
415 llvm_unreachable(
"Unhandled storage kind");
419 const llvm::MemoryBuffer *MainFileBuffer,
421 llvm::vfs::FileSystem *VFS)
const {
424 Bounds.
Size <= MainFileBuffer->getBufferSize() &&
425 "Buffer is too large. Bounds were calculated from a different buffer?");
427 auto PreambleInvocation = std::make_shared<CompilerInvocation>(Invocation);
429 PreambleInvocation->getPreprocessorOpts();
435 if (PreambleBytes.size() != Bounds.
Size ||
437 !std::equal(PreambleBytes.begin(), PreambleBytes.end(),
438 MainFileBuffer->getBuffer().begin()))
446 std::map<llvm::sys::fs::UniqueID, PreambleFileHash> OverriddenFiles;
447 for (
const auto &R : PreprocessorOpts.RemappedFiles) {
448 llvm::vfs::Status Status;
455 OverriddenFiles[Status.getUniqueID()] = PreambleFileHash::createForFile(
456 Status.getSize(), llvm::sys::toTimeT(Status.getLastModificationTime()));
460 llvm::StringMap<PreambleFileHash> OverridenFileBuffers;
461 for (
const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
462 const PrecompiledPreamble::PreambleFileHash PreambleHash =
463 PreambleFileHash::createForMemoryBuffer(RB.second);
464 llvm::vfs::Status Status;
466 OverriddenFiles[Status.getUniqueID()] = PreambleHash;
468 OverridenFileBuffers[RB.first] = PreambleHash;
472 for (
const auto &F : FilesInPreamble) {
473 auto OverridenFileBuffer = OverridenFileBuffers.find(F.first());
474 if (OverridenFileBuffer != OverridenFileBuffers.end()) {
477 if (OverridenFileBuffer->second != F.second)
482 llvm::vfs::Status Status;
489 std::map<llvm::sys::fs::UniqueID, PreambleFileHash>::iterator Overridden =
490 OverriddenFiles.find(Status.getUniqueID());
491 if (Overridden != OverriddenFiles.end()) {
494 if (Overridden->second != F.second)
501 if (Status.getSize() != uint64_t(F.second.Size) ||
502 llvm::sys::toTimeT(Status.getLastModificationTime()) !=
511 llvm::MemoryBuffer *MainFileBuffer)
const {
512 PreambleBounds Bounds(PreambleBytes.size(), PreambleEndsAtStartOfLine);
513 configurePreamble(Bounds, CI, VFS, MainFileBuffer);
518 llvm::MemoryBuffer *MainFileBuffer)
const {
520 configurePreamble(Bounds, CI, VFS, MainFileBuffer);
524 PCHStorage Storage, std::vector<char> PreambleBytes,
525 bool PreambleEndsAtStartOfLine,
526 llvm::StringMap<PreambleFileHash> FilesInPreamble)
527 : Storage(std::move(Storage)), FilesInPreamble(std::move(FilesInPreamble)),
528 PreambleBytes(std::move(PreambleBytes)),
529 PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {
530 assert(this->Storage.getKind() != PCHStorage::Kind::Empty);
533 llvm::ErrorOr<PrecompiledPreamble::TempPCHFile>
534 PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile() {
538 if (
const char *TmpFile = ::getenv(
"CINDEXTEST_PREAMBLE_FILE"))
539 return TempPCHFile(TmpFile);
546 auto EC = llvm::sys::fs::createTemporaryFile(
"preamble",
"pch", FD, File);
550 llvm::sys::Process::SafelyCloseFileDescriptor(FD);
551 return TempPCHFile(std::move(File).str());
554 PrecompiledPreamble::TempPCHFile::TempPCHFile(std::string FilePath)
555 : FilePath(std::move(FilePath)) {
556 TemporaryFiles::getInstance().addFile(*this->FilePath);
559 PrecompiledPreamble::TempPCHFile::TempPCHFile(TempPCHFile &&Other) {
560 FilePath = std::move(Other.FilePath);
561 Other.FilePath =
None;
564 PrecompiledPreamble::TempPCHFile &PrecompiledPreamble::TempPCHFile::
565 operator=(TempPCHFile &&Other) {
566 RemoveFileIfPresent();
568 FilePath = std::move(Other.FilePath);
569 Other.FilePath =
None;
573 PrecompiledPreamble::TempPCHFile::~TempPCHFile() { RemoveFileIfPresent(); }
575 void PrecompiledPreamble::TempPCHFile::RemoveFileIfPresent() {
577 TemporaryFiles::getInstance().removeFile(*FilePath);
582 llvm::StringRef PrecompiledPreamble::TempPCHFile::getFilePath()
const {
583 assert(FilePath &&
"TempPCHFile doesn't have a FilePath. Had it been moved?");
587 PrecompiledPreamble::PCHStorage::PCHStorage(TempPCHFile File)
588 : StorageKind(Kind::TempFile) {
589 new (&asFile()) TempPCHFile(std::move(File));
592 PrecompiledPreamble::PCHStorage::PCHStorage(InMemoryPreamble Memory)
593 : StorageKind(Kind::InMemory) {
594 new (&asMemory()) InMemoryPreamble(std::move(Memory));
597 PrecompiledPreamble::PCHStorage::PCHStorage(PCHStorage &&Other) : PCHStorage() {
598 *
this = std::move(Other);
601 PrecompiledPreamble::PCHStorage &PrecompiledPreamble::PCHStorage::
602 operator=(PCHStorage &&Other) {
605 StorageKind = Other.StorageKind;
606 switch (StorageKind) {
611 new (&asFile()) TempPCHFile(std::move(Other.asFile()));
614 new (&asMemory()) InMemoryPreamble(std::move(Other.asMemory()));
622 PrecompiledPreamble::PCHStorage::~PCHStorage() { destroy(); }
624 PrecompiledPreamble::PCHStorage::Kind
629 PrecompiledPreamble::TempPCHFile &PrecompiledPreamble::PCHStorage::asFile() {
630 assert(
getKind() == Kind::TempFile);
631 return *
reinterpret_cast<TempPCHFile *
>(Storage.buffer);
634 const PrecompiledPreamble::TempPCHFile &
635 PrecompiledPreamble::PCHStorage::asFile()
const {
636 return const_cast<PCHStorage *
>(
this)->asFile();
639 PrecompiledPreamble::InMemoryPreamble &
640 PrecompiledPreamble::PCHStorage::asMemory() {
641 assert(
getKind() == Kind::InMemory);
642 return *
reinterpret_cast<InMemoryPreamble *
>(Storage.buffer);
645 const PrecompiledPreamble::InMemoryPreamble &
646 PrecompiledPreamble::PCHStorage::asMemory()
const {
647 return const_cast<PCHStorage *
>(
this)->asMemory();
650 void PrecompiledPreamble::PCHStorage::destroy() {
651 switch (StorageKind) {
655 asFile().~TempPCHFile();
658 asMemory().~InMemoryPreamble();
663 void PrecompiledPreamble::PCHStorage::setEmpty() {
665 StorageKind = Kind::Empty;
668 PrecompiledPreamble::PreambleFileHash
669 PrecompiledPreamble::PreambleFileHash::createForFile(off_t Size,
673 Result.ModTime = ModTime;
678 PrecompiledPreamble::PreambleFileHash
679 PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(
680 const llvm::MemoryBuffer *Buffer) {
682 Result.Size = Buffer->getBufferSize();
686 MD5Ctx.update(Buffer->getBuffer().data());
687 MD5Ctx.final(Result.MD5);
692 void PrecompiledPreamble::configurePreamble(
695 llvm::MemoryBuffer *MainFileBuffer)
const {
702 PreprocessorOpts.addRemappedFile(MainFilePath, MainFileBuffer);
705 PreprocessorOpts.PrecompiledPreambleBytes.first = Bounds.
Size;
706 PreprocessorOpts.PrecompiledPreambleBytes.second =
708 PreprocessorOpts.DisablePCHValidation =
true;
710 setupPreambleStorage(Storage, PreprocessorOpts, VFS);
713 void PrecompiledPreamble::setupPreambleStorage(
716 if (Storage.getKind() == PCHStorage::Kind::TempFile) {
717 const TempPCHFile &PCHFile = Storage.asFile();
722 llvm::vfs::getRealFileSystem();
723 auto PCHPath = PCHFile.getFilePath();
724 if (VFS == RealFS || VFS->exists(PCHPath))
726 auto Buf = RealFS->getBufferForFile(PCHPath);
736 VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(*Buf), VFS);
738 assert(Storage.getKind() == PCHStorage::Kind::InMemory);
741 StringRef PCHPath = getInMemoryPreamblePath();
744 auto Buf = llvm::MemoryBuffer::getMemBuffer(Storage.asMemory().Data);
745 VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(Buf), VFS);
761 return std::error_code(static_cast<int>(Error), *BuildPreambleErrCategory);
765 return "build-preamble.error";
769 switch (static_cast<BuildPreambleError>(condition)) {
771 return "Could not create temporary file for PCH";
773 return "CreateTargetInfo() return null";
775 return "BeginSourceFile() return an error";
777 return "Could not emit PCH";
779 return "Command line arguments must contain exactly one source file";
781 llvm_unreachable(
"unexpected BuildPreambleError");
std::size_t getSize() const
Returns the size, in bytes, that preamble takes on disk or in memory.
Describes the bounds (start, size) of the preamble and a flag required by PreprocessorOptions::Precom...
Implements support for file system lookup, file system caching, and directory search management...
bool CanReuse(const CompilerInvocation &Invocation, const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, llvm::vfs::FileSystem *VFS) const
Check whether PrecompiledPreamble can be reused for the new contents(MainFileBuffer) of the main file...
An interface for collecting the dependencies of a compilation.
The translation unit is a prefix to a translation unit, and is not complete.
InMemoryModuleCache & getModuleCache() const
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
void addRemappedFile(StringRef From, StringRef To)
FileManager & getFileManager() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
void HandleTranslationUnit(ASTContext &Ctx) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
static bool moveOnNoError(llvm::ErrorOr< T > Val, T &Output)
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
__DEVICE__ int max(int __a, int __b)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
unsigned RelocatablePCH
When generating PCH files, instruct the AST writer to create relocatable PCH files.
static bool ComputeASTConsumerArguments(CompilerInstance &CI, std::string &Sysroot)
Compute the AST consumer arguments that will be used to create the PCHGenerator instance returned by ...
static llvm::ManagedStatic< BuildPreambleErrorCategory > BuildPreambleErrCategory
std::error_code make_error_code(BuildPreambleError Error)
FrontendOptions & getFrontendOpts()
SmallVector< FrontendInputFile, 0 > Inputs
The input files and their types.
Concrete class used by the front-end to report problems and issues.
bool RetainRemappedFileBuffers
Whether the compiler instance should retain (i.e., not free) the buffers associated with remapped fil...
void OverridePreamble(CompilerInvocation &CI, IntrusiveRefCntPtr< llvm::vfs::FileSystem > &VFS, llvm::MemoryBuffer *MainFileBuffer) const
Configure CI to use this preamble.
void Reset()
Reset the state of the diagnostic object to its initial configuration.
FrontendOptions & getFrontendOpts()
bool PreambleEndsAtStartOfLine
Whether the preamble ends at the start of a new line.
A set of callbacks to gather useful information while building a preamble.
const char * name() const noexcept override
PreambleBounds getBounds() const
PreambleBounds used to build the preamble.
void AddImplicitPreamble(CompilerInvocation &CI, IntrusiveRefCntPtr< llvm::vfs::FileSystem > &VFS, llvm::MemoryBuffer *MainFileBuffer) const
Changes options inside CI to use PCH from this preamble.
static PreambleBounds ComputePreamble(StringRef Buffer, const LangOptions &LangOpts, unsigned MaxLines=0)
Compute the preamble of the given file.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
Defines the clang::Preprocessor interface.
static TargetInfo * CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr< TargetOptions > &Opts)
Construct a target for the given options.
bool GeneratePreamble
True indicates that a preamble is being generated.
PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, llvm::MemoryBuffer *Buffer, unsigned MaxLines)
Runs lexer to compute suggested preamble bounds.
The result type of a method or function.
In-memory cache for modules.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
virtual CommentHandler * getCommentHandler()
The returned CommentHandler will be added to the preprocessor if not null.
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
void ProcessWarningOptions(DiagnosticsEngine &Diags, const DiagnosticOptions &Opts, bool ReportDiags=true)
ProcessWarningOptions - Initialize the diagnostic client and process the warning options specified on...
Abstract base class to use for AST consumer-based frontend actions.
virtual void BeforeExecute(CompilerInstance &CI)
Called before FrontendAction::BeginSourceFile.
virtual void AfterPCHEmitted(ASTWriter &Writer)
Called after PCH has been emitted.
PrecompiledPreamble(PrecompiledPreamble &&)=default
std::string message(int condition) const override
Dataflow Directional Tag Classes.
A class holding a PCH and all information to check whether it is valid to reuse the PCH for the subse...
PreprocessorOptions & getPreprocessorOpts()
IntrusiveRefCntPtr< llvm::vfs::FileSystem > createVFSFromCompilerInvocation(const CompilerInvocation &CI, DiagnosticsEngine &Diags)
const llvm::MemoryBuffer * getMemoryBufferForFile(const FileEntry *File, bool *Invalid=nullptr)
Retrieve the memory buffer associated with the given file.
FileID getMainFileID() const
Returns the FileID of the main source file.
Helper class for holding the data necessary to invoke the compiler.
FrontendOptions - Options for controlling the behavior of the frontend.
virtual void AfterExecute(CompilerInstance &CI)
Called after FrontendAction::Execute(), but before FrontendAction::EndSourceFile().
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, PreambleCallbacks &Callbacks)
Try to build PrecompiledPreamble for Invocation.
llvm::ErrorOr< const FileEntry * > getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
unsigned Size
Size of the preamble in bytes.
Generate pre-compiled header.
Preprocessor & getPreprocessor() const
Return the current preprocessor.
TranslationUnitKind
Describes the kind of translation unit being processed.
Writes an AST file containing the contents of a translation unit.
std::pair< unsigned, bool > PrecompiledPreambleBytes
If non-zero, the implicit PCH include is actually a precompiled preamble that covers this number of b...
Defines the clang::TargetInfo interface.
static Decl::Kind getKind(const Decl *D)
LLVM IR: we accept this so that we can run the optimizer on it, and compile it to assembly or object ...
An abstract superclass that describes a custom extension to the module/precompiled header file format...
AST and semantic-analysis consumer that generates a precompiled header from the parsed source code...
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.
LangOptions * getLangOpts()
virtual void HandleTopLevelDecl(DeclGroupRef DG)
Called for each TopLevelDecl.
This class handles loading and caching of source files into memory.
virtual std::unique_ptr< PPCallbacks > createPPCallbacks()
Creates wrapper class for PPCallbacks so we can also process information about includes that are insi...
Engages in a tight little dance with the lexer to efficiently preprocess tokens.