clang  6.0.0svn
PrecompiledPreamble.cpp
Go to the documentation of this file.
1 //===--- PrecompiledPreamble.cpp - Build precompiled preambles --*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Helper class to build precompiled preamble.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/AST/DeclObjC.h"
16 #include "clang/Basic/TargetInfo.h"
22 #include "clang/Lex/Lexer.h"
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/Mutex.h"
31 #include "llvm/Support/MutexGuard.h"
32 #include "llvm/Support/Process.h"
33 
34 #include <utility>
35 
36 using namespace clang;
37 
38 namespace {
39 
40 StringRef getInMemoryPreamblePath() {
41 #if defined(LLVM_ON_UNIX)
42  return "/__clang_tmp/___clang_inmemory_preamble___";
43 #elif defined(LLVM_ON_WIN32)
44  return "C:\\__clang_tmp\\___clang_inmemory_preamble___";
45 #else
46 #warning "Unknown platform. Defaulting to UNIX-style paths for in-memory PCHs"
47  return "/__clang_tmp/___clang_inmemory_preamble___";
48 #endif
49 }
50 
52 createVFSOverlayForPreamblePCH(StringRef PCHFilename,
53  std::unique_ptr<llvm::MemoryBuffer> PCHBuffer,
55  // We want only the PCH file from the real filesystem to be available,
56  // so we create an in-memory VFS with just that and overlay it on top.
59  PCHFS->addFile(PCHFilename, 0, std::move(PCHBuffer));
61  new vfs::OverlayFileSystem(VFS));
62  Overlay->pushOverlay(PCHFS);
63  return Overlay;
64 }
65 
66 /// Keeps a track of files to be deleted in destructor.
67 class TemporaryFiles {
68 public:
69  // A static instance to be used by all clients.
70  static TemporaryFiles &getInstance();
71 
72 private:
73  // Disallow constructing the class directly.
74  TemporaryFiles() = default;
75  // Disallow copy.
76  TemporaryFiles(const TemporaryFiles &) = delete;
77 
78 public:
79  ~TemporaryFiles();
80 
81  /// Adds \p File to a set of tracked files.
82  void addFile(StringRef File);
83 
84  /// Remove \p File from disk and from the set of tracked files.
85  void removeFile(StringRef File);
86 
87 private:
88  llvm::sys::SmartMutex<false> Mutex;
89  llvm::StringSet<> Files;
90 };
91 
92 TemporaryFiles &TemporaryFiles::getInstance() {
93  static TemporaryFiles Instance;
94  return Instance;
95 }
96 
97 TemporaryFiles::~TemporaryFiles() {
98  llvm::MutexGuard Guard(Mutex);
99  for (const auto &File : Files)
100  llvm::sys::fs::remove(File.getKey());
101 }
102 
103 void TemporaryFiles::addFile(StringRef File) {
104  llvm::MutexGuard Guard(Mutex);
105  auto IsInserted = Files.insert(File).second;
106  (void)IsInserted;
107  assert(IsInserted && "File has already been added");
108 }
109 
110 void TemporaryFiles::removeFile(StringRef File) {
111  llvm::MutexGuard Guard(Mutex);
112  auto WasPresent = Files.erase(File);
113  (void)WasPresent;
114  assert(WasPresent && "File was not tracked");
115  llvm::sys::fs::remove(File);
116 }
117 
118 class PreambleMacroCallbacks : public PPCallbacks {
119 public:
120  PreambleMacroCallbacks(PreambleCallbacks &Callbacks) : Callbacks(Callbacks) {}
121 
122  void MacroDefined(const Token &MacroNameTok,
123  const MacroDirective *MD) override {
124  Callbacks.HandleMacroDefined(MacroNameTok, MD);
125  }
126 
127 private:
128  PreambleCallbacks &Callbacks;
129 };
130 
131 class PrecompilePreambleAction : public ASTFrontendAction {
132 public:
133  PrecompilePreambleAction(std::string *InMemStorage,
134  PreambleCallbacks &Callbacks)
135  : InMemStorage(InMemStorage), Callbacks(Callbacks) {}
136 
137  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
138  StringRef InFile) override;
139 
140  bool hasEmittedPreamblePCH() const { return HasEmittedPreamblePCH; }
141 
142  void setEmittedPreamblePCH(ASTWriter &Writer) {
143  this->HasEmittedPreamblePCH = true;
144  Callbacks.AfterPCHEmitted(Writer);
145  }
146 
147  bool shouldEraseOutputFiles() override { return !hasEmittedPreamblePCH(); }
148  bool hasCodeCompletionSupport() const override { return false; }
149  bool hasASTFileSupport() const override { return false; }
150  TranslationUnitKind getTranslationUnitKind() override { return TU_Prefix; }
151 
152 private:
153  friend class PrecompilePreambleConsumer;
154 
155  bool HasEmittedPreamblePCH = false;
156  std::string *InMemStorage;
157  PreambleCallbacks &Callbacks;
158 };
159 
160 class PrecompilePreambleConsumer : public PCHGenerator {
161 public:
162  PrecompilePreambleConsumer(PrecompilePreambleAction &Action,
163  const Preprocessor &PP, StringRef isysroot,
164  std::unique_ptr<raw_ostream> Out)
165  : PCHGenerator(PP, "", isysroot, std::make_shared<PCHBuffer>(),
166  ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
167  /*AllowASTWithErrors=*/true),
168  Action(Action), Out(std::move(Out)) {}
169 
170  bool HandleTopLevelDecl(DeclGroupRef DG) override {
171  Action.Callbacks.HandleTopLevelDecl(DG);
172  return true;
173  }
174 
175  void HandleTranslationUnit(ASTContext &Ctx) override {
177  if (!hasEmittedPCH())
178  return;
179 
180  // Write the generated bitstream to "Out".
181  *Out << getPCH();
182  // Make sure it hits disk now.
183  Out->flush();
184  // Free the buffer.
186  getPCH() = std::move(Empty);
187 
188  Action.setEmittedPreamblePCH(getWriter());
189  }
190 
191 private:
192  PrecompilePreambleAction &Action;
193  std::unique_ptr<raw_ostream> Out;
194 };
195 
196 std::unique_ptr<ASTConsumer>
197 PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
198  StringRef InFile) {
199  std::string Sysroot;
201  return nullptr;
202 
203  std::unique_ptr<llvm::raw_ostream> OS;
204  if (InMemStorage) {
205  OS = llvm::make_unique<llvm::raw_string_ostream>(*InMemStorage);
206  } else {
207  std::string OutputFile;
208  OS = GeneratePCHAction::CreateOutputFile(CI, InFile, OutputFile);
209  }
210  if (!OS)
211  return nullptr;
212 
214  Sysroot.clear();
215 
217  llvm::make_unique<PreambleMacroCallbacks>(Callbacks));
218  return llvm::make_unique<PrecompilePreambleConsumer>(
219  *this, CI.getPreprocessor(), Sysroot, std::move(OS));
220 }
221 
222 template <class T> bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
223  if (!Val)
224  return false;
225  Output = std::move(*Val);
226  return true;
227 }
228 
229 } // namespace
230 
232  llvm::MemoryBuffer *Buffer,
233  unsigned MaxLines) {
234  return Lexer::ComputePreamble(Buffer->getBuffer(), LangOpts, MaxLines);
235 }
236 
237 llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build(
238  const CompilerInvocation &Invocation,
239  const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
241  std::shared_ptr<PCHContainerOperations> PCHContainerOps, bool StoreInMemory,
242  PreambleCallbacks &Callbacks) {
243  assert(VFS && "VFS is null");
244 
245  if (!Bounds.Size)
247 
248  auto PreambleInvocation = std::make_shared<CompilerInvocation>(Invocation);
249  FrontendOptions &FrontendOpts = PreambleInvocation->getFrontendOpts();
250  PreprocessorOptions &PreprocessorOpts =
251  PreambleInvocation->getPreprocessorOpts();
252 
254  if (!StoreInMemory) {
255  // Create a temporary file for the precompiled preamble. In rare
256  // circumstances, this can fail.
257  llvm::ErrorOr<PrecompiledPreamble::TempPCHFile> PreamblePCHFile =
258  PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile();
259  if (!PreamblePCHFile)
261  TempFile = std::move(*PreamblePCHFile);
262  }
263 
264  PCHStorage Storage = StoreInMemory ? PCHStorage(InMemoryPreamble())
265  : PCHStorage(std::move(*TempFile));
266 
267  // Save the preamble text for later; we'll need to compare against it for
268  // subsequent reparses.
269  std::vector<char> PreambleBytes(MainFileBuffer->getBufferStart(),
270  MainFileBuffer->getBufferStart() +
271  Bounds.Size);
272  bool PreambleEndsAtStartOfLine = Bounds.PreambleEndsAtStartOfLine;
273 
274  // Tell the compiler invocation to generate a temporary precompiled header.
275  FrontendOpts.ProgramAction = frontend::GeneratePCH;
276  FrontendOpts.OutputFile = StoreInMemory ? getInMemoryPreamblePath()
277  : Storage.asFile().getFilePath();
278  PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
279  PreprocessorOpts.PrecompiledPreambleBytes.second = false;
280  // Inform preprocessor to record conditional stack when building the preamble.
281  PreprocessorOpts.GeneratePreamble = true;
282 
283  // Create the compiler instance to use for building the precompiled preamble.
284  std::unique_ptr<CompilerInstance> Clang(
285  new CompilerInstance(std::move(PCHContainerOps)));
286 
287  // Recover resources if we crash before exiting this method.
288  llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> CICleanup(
289  Clang.get());
290 
291  Clang->setInvocation(std::move(PreambleInvocation));
292  Clang->setDiagnostics(&Diagnostics);
293 
294  // Create the target instance.
295  Clang->setTarget(TargetInfo::CreateTargetInfo(
296  Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
297  if (!Clang->hasTarget())
299 
300  // Inform the target of the language options.
301  //
302  // FIXME: We shouldn't need to do this, the target should be immutable once
303  // created. This complexity should be lifted elsewhere.
304  Clang->getTarget().adjust(Clang->getLangOpts());
305 
306  assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
307  "Invocation must have exactly one source file!");
308  assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
310  "FIXME: AST inputs not yet supported here!");
311  assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
313  "IR inputs not support here!");
314 
315  // Clear out old caches and data.
316  Diagnostics.Reset();
317  ProcessWarningOptions(Diagnostics, Clang->getDiagnosticOpts());
318 
319  VFS =
320  createVFSFromCompilerInvocation(Clang->getInvocation(), Diagnostics, VFS);
321  if (!VFS)
323 
324  // Create a file manager object to provide access to and cache the filesystem.
325  Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS));
326 
327  // Create the source manager.
328  Clang->setSourceManager(
329  new SourceManager(Diagnostics, Clang->getFileManager()));
330 
331  auto PreambleDepCollector = std::make_shared<DependencyCollector>();
332  Clang->addDependencyCollector(PreambleDepCollector);
333 
334  // Remap the main source file to the preamble buffer.
335  StringRef MainFilePath = FrontendOpts.Inputs[0].getFile();
336  auto PreambleInputBuffer = llvm::MemoryBuffer::getMemBufferCopy(
337  MainFileBuffer->getBuffer().slice(0, Bounds.Size), MainFilePath);
338  if (PreprocessorOpts.RetainRemappedFileBuffers) {
339  // MainFileBuffer will be deleted by unique_ptr after leaving the method.
340  PreprocessorOpts.addRemappedFile(MainFilePath, PreambleInputBuffer.get());
341  } else {
342  // In that case, remapped buffer will be deleted by CompilerInstance on
343  // BeginSourceFile, so we call release() to avoid double deletion.
344  PreprocessorOpts.addRemappedFile(MainFilePath,
345  PreambleInputBuffer.release());
346  }
347 
348  std::unique_ptr<PrecompilePreambleAction> Act;
349  Act.reset(new PrecompilePreambleAction(
350  StoreInMemory ? &Storage.asMemory().Data : nullptr, Callbacks));
351  if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
353 
354  Act->Execute();
355 
356  // Run the callbacks.
357  Callbacks.AfterExecute(*Clang);
358 
359  Act->EndSourceFile();
360 
361  if (!Act->hasEmittedPreamblePCH())
363 
364  // Keep track of all of the files that the source manager knows about,
365  // so we can verify whether they have changed or not.
366  llvm::StringMap<PrecompiledPreamble::PreambleFileHash> FilesInPreamble;
367 
368  SourceManager &SourceMgr = Clang->getSourceManager();
369  for (auto &Filename : PreambleDepCollector->getDependencies()) {
370  const FileEntry *File = Clang->getFileManager().getFile(Filename);
371  if (!File || File == SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()))
372  continue;
373  if (time_t ModTime = File->getModificationTime()) {
374  FilesInPreamble[File->getName()] =
375  PrecompiledPreamble::PreambleFileHash::createForFile(File->getSize(),
376  ModTime);
377  } else {
378  llvm::MemoryBuffer *Buffer = SourceMgr.getMemoryBufferForFile(File);
379  FilesInPreamble[File->getName()] =
380  PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(Buffer);
381  }
382  }
383 
384  return PrecompiledPreamble(std::move(Storage), std::move(PreambleBytes),
385  PreambleEndsAtStartOfLine,
386  std::move(FilesInPreamble));
387 }
388 
390  return PreambleBounds(PreambleBytes.size(), PreambleEndsAtStartOfLine);
391 }
392 
394  const llvm::MemoryBuffer *MainFileBuffer,
395  PreambleBounds Bounds,
396  vfs::FileSystem *VFS) const {
397 
398  assert(
399  Bounds.Size <= MainFileBuffer->getBufferSize() &&
400  "Buffer is too large. Bounds were calculated from a different buffer?");
401 
402  auto PreambleInvocation = std::make_shared<CompilerInvocation>(Invocation);
403  PreprocessorOptions &PreprocessorOpts =
404  PreambleInvocation->getPreprocessorOpts();
405 
406  if (!Bounds.Size)
407  return false;
408 
409  // We've previously computed a preamble. Check whether we have the same
410  // preamble now that we did before, and that there's enough space in
411  // the main-file buffer within the precompiled preamble to fit the
412  // new main file.
413  if (PreambleBytes.size() != Bounds.Size ||
414  PreambleEndsAtStartOfLine != Bounds.PreambleEndsAtStartOfLine ||
415  memcmp(PreambleBytes.data(), MainFileBuffer->getBufferStart(),
416  Bounds.Size) != 0)
417  return false;
418  // The preamble has not changed. We may be able to re-use the precompiled
419  // preamble.
420 
421  // Check that none of the files used by the preamble have changed.
422  // First, make a record of those files that have been overridden via
423  // remapping or unsaved_files.
424  std::map<llvm::sys::fs::UniqueID, PreambleFileHash> OverriddenFiles;
425  for (const auto &R : PreprocessorOpts.RemappedFiles) {
426  vfs::Status Status;
427  if (!moveOnNoError(VFS->status(R.second), Status)) {
428  // If we can't stat the file we're remapping to, assume that something
429  // horrible happened.
430  return false;
431  }
432 
433  OverriddenFiles[Status.getUniqueID()] = PreambleFileHash::createForFile(
434  Status.getSize(), llvm::sys::toTimeT(Status.getLastModificationTime()));
435  }
436 
437  for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
438  vfs::Status Status;
439  if (!moveOnNoError(VFS->status(RB.first), Status))
440  return false;
441 
442  OverriddenFiles[Status.getUniqueID()] =
443  PreambleFileHash::createForMemoryBuffer(RB.second);
444  }
445 
446  // Check whether anything has changed.
447  for (const auto &F : FilesInPreamble) {
448  vfs::Status Status;
449  if (!moveOnNoError(VFS->status(F.first()), Status)) {
450  // If we can't stat the file, assume that something horrible happened.
451  return false;
452  }
453 
454  std::map<llvm::sys::fs::UniqueID, PreambleFileHash>::iterator Overridden =
455  OverriddenFiles.find(Status.getUniqueID());
456  if (Overridden != OverriddenFiles.end()) {
457  // This file was remapped; check whether the newly-mapped file
458  // matches up with the previous mapping.
459  if (Overridden->second != F.second)
460  return false;
461  continue;
462  }
463 
464  // The file was not remapped; check whether it has changed on disk.
465  if (Status.getSize() != uint64_t(F.second.Size) ||
466  llvm::sys::toTimeT(Status.getLastModificationTime()) !=
467  F.second.ModTime)
468  return false;
469  }
470  return true;
471 }
472 
475  llvm::MemoryBuffer *MainFileBuffer) const {
476  assert(VFS && "VFS must not be null");
477 
478  auto &PreprocessorOpts = CI.getPreprocessorOpts();
479 
480  // Remap main file to point to MainFileBuffer.
481  auto MainFilePath = CI.getFrontendOpts().Inputs[0].getFile();
482  PreprocessorOpts.addRemappedFile(MainFilePath, MainFileBuffer);
483 
484  // Configure ImpicitPCHInclude.
485  PreprocessorOpts.PrecompiledPreambleBytes.first = PreambleBytes.size();
486  PreprocessorOpts.PrecompiledPreambleBytes.second = PreambleEndsAtStartOfLine;
487  PreprocessorOpts.DisablePCHValidation = true;
488 
489  setupPreambleStorage(Storage, PreprocessorOpts, VFS);
490 }
491 
493  PCHStorage Storage, std::vector<char> PreambleBytes,
494  bool PreambleEndsAtStartOfLine,
495  llvm::StringMap<PreambleFileHash> FilesInPreamble)
496  : Storage(std::move(Storage)), FilesInPreamble(std::move(FilesInPreamble)),
497  PreambleBytes(std::move(PreambleBytes)),
498  PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {
499  assert(this->Storage.getKind() != PCHStorage::Kind::Empty);
500 }
501 
502 llvm::ErrorOr<PrecompiledPreamble::TempPCHFile>
503 PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile() {
504  // FIXME: This is a hack so that we can override the preamble file during
505  // crash-recovery testing, which is the only case where the preamble files
506  // are not necessarily cleaned up.
507  const char *TmpFile = ::getenv("CINDEXTEST_PREAMBLE_FILE");
508  if (TmpFile)
509  return TempPCHFile::createFromCustomPath(TmpFile);
510  return TempPCHFile::createInSystemTempDir("preamble", "pch");
511 }
512 
513 llvm::ErrorOr<PrecompiledPreamble::TempPCHFile>
514 PrecompiledPreamble::TempPCHFile::createInSystemTempDir(const Twine &Prefix,
515  StringRef Suffix) {
517  // Using a version of createTemporaryFile with a file descriptor guarantees
518  // that we would never get a race condition in a multi-threaded setting (i.e.,
519  // multiple threads getting the same temporary path).
520  int FD;
521  auto EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, FD, File);
522  if (EC)
523  return EC;
524  // We only needed to make sure the file exists, close the file right away.
525  llvm::sys::Process::SafelyCloseFileDescriptor(FD);
526  return TempPCHFile(std::move(File).str());
527 }
528 
529 llvm::ErrorOr<PrecompiledPreamble::TempPCHFile>
530 PrecompiledPreamble::TempPCHFile::createFromCustomPath(const Twine &Path) {
531  return TempPCHFile(Path.str());
532 }
533 
534 PrecompiledPreamble::TempPCHFile::TempPCHFile(std::string FilePath)
535  : FilePath(std::move(FilePath)) {
536  TemporaryFiles::getInstance().addFile(*this->FilePath);
537 }
538 
539 PrecompiledPreamble::TempPCHFile::TempPCHFile(TempPCHFile &&Other) {
540  FilePath = std::move(Other.FilePath);
541  Other.FilePath = None;
542 }
543 
544 PrecompiledPreamble::TempPCHFile &PrecompiledPreamble::TempPCHFile::
545 operator=(TempPCHFile &&Other) {
546  RemoveFileIfPresent();
547 
548  FilePath = std::move(Other.FilePath);
549  Other.FilePath = None;
550  return *this;
551 }
552 
553 PrecompiledPreamble::TempPCHFile::~TempPCHFile() { RemoveFileIfPresent(); }
554 
555 void PrecompiledPreamble::TempPCHFile::RemoveFileIfPresent() {
556  if (FilePath) {
557  TemporaryFiles::getInstance().removeFile(*FilePath);
558  FilePath = None;
559  }
560 }
561 
562 llvm::StringRef PrecompiledPreamble::TempPCHFile::getFilePath() const {
563  assert(FilePath && "TempPCHFile doesn't have a FilePath. Had it been moved?");
564  return *FilePath;
565 }
566 
567 PrecompiledPreamble::PCHStorage::PCHStorage(TempPCHFile File)
568  : StorageKind(Kind::TempFile) {
569  new (&asFile()) TempPCHFile(std::move(File));
570 }
571 
572 PrecompiledPreamble::PCHStorage::PCHStorage(InMemoryPreamble Memory)
573  : StorageKind(Kind::InMemory) {
574  new (&asMemory()) InMemoryPreamble(std::move(Memory));
575 }
576 
577 PrecompiledPreamble::PCHStorage::PCHStorage(PCHStorage &&Other) : PCHStorage() {
578  *this = std::move(Other);
579 }
580 
581 PrecompiledPreamble::PCHStorage &PrecompiledPreamble::PCHStorage::
582 operator=(PCHStorage &&Other) {
583  destroy();
584 
585  StorageKind = Other.StorageKind;
586  switch (StorageKind) {
587  case Kind::Empty:
588  // do nothing;
589  break;
590  case Kind::TempFile:
591  new (&asFile()) TempPCHFile(std::move(Other.asFile()));
592  break;
593  case Kind::InMemory:
594  new (&asMemory()) InMemoryPreamble(std::move(Other.asMemory()));
595  break;
596  }
597 
598  Other.setEmpty();
599  return *this;
600 }
601 
602 PrecompiledPreamble::PCHStorage::~PCHStorage() { destroy(); }
603 
604 PrecompiledPreamble::PCHStorage::Kind
606  return StorageKind;
607 }
608 
609 PrecompiledPreamble::TempPCHFile &PrecompiledPreamble::PCHStorage::asFile() {
610  assert(getKind() == Kind::TempFile);
611  return *reinterpret_cast<TempPCHFile *>(Storage.buffer);
612 }
613 
614 const PrecompiledPreamble::TempPCHFile &
615 PrecompiledPreamble::PCHStorage::asFile() const {
616  return const_cast<PCHStorage *>(this)->asFile();
617 }
618 
619 PrecompiledPreamble::InMemoryPreamble &
620 PrecompiledPreamble::PCHStorage::asMemory() {
621  assert(getKind() == Kind::InMemory);
622  return *reinterpret_cast<InMemoryPreamble *>(Storage.buffer);
623 }
624 
625 const PrecompiledPreamble::InMemoryPreamble &
626 PrecompiledPreamble::PCHStorage::asMemory() const {
627  return const_cast<PCHStorage *>(this)->asMemory();
628 }
629 
630 void PrecompiledPreamble::PCHStorage::destroy() {
631  switch (StorageKind) {
632  case Kind::Empty:
633  return;
634  case Kind::TempFile:
635  asFile().~TempPCHFile();
636  return;
637  case Kind::InMemory:
638  asMemory().~InMemoryPreamble();
639  return;
640  }
641 }
642 
643 void PrecompiledPreamble::PCHStorage::setEmpty() {
644  destroy();
645  StorageKind = Kind::Empty;
646 }
647 
648 PrecompiledPreamble::PreambleFileHash
649 PrecompiledPreamble::PreambleFileHash::createForFile(off_t Size,
650  time_t ModTime) {
651  PreambleFileHash Result;
652  Result.Size = Size;
653  Result.ModTime = ModTime;
654  Result.MD5 = {};
655  return Result;
656 }
657 
658 PrecompiledPreamble::PreambleFileHash
659 PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(
660  const llvm::MemoryBuffer *Buffer) {
661  PreambleFileHash Result;
662  Result.Size = Buffer->getBufferSize();
663  Result.ModTime = 0;
664 
665  llvm::MD5 MD5Ctx;
666  MD5Ctx.update(Buffer->getBuffer().data());
667  MD5Ctx.final(Result.MD5);
668 
669  return Result;
670 }
671 
672 void PrecompiledPreamble::setupPreambleStorage(
673  const PCHStorage &Storage, PreprocessorOptions &PreprocessorOpts,
675  if (Storage.getKind() == PCHStorage::Kind::TempFile) {
676  const TempPCHFile &PCHFile = Storage.asFile();
677  PreprocessorOpts.ImplicitPCHInclude = PCHFile.getFilePath();
678 
679  // Make sure we can access the PCH file even if we're using a VFS
681  auto PCHPath = PCHFile.getFilePath();
682  if (VFS == RealFS || VFS->exists(PCHPath))
683  return;
684  auto Buf = RealFS->getBufferForFile(PCHPath);
685  if (!Buf) {
686  // We can't read the file even from RealFS, this is clearly an error,
687  // but we'll just leave the current VFS as is and let clang's code
688  // figure out what to do with missing PCH.
689  return;
690  }
691 
692  // We have a slight inconsistency here -- we're using the VFS to
693  // read files, but the PCH was generated in the real file system.
694  VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(*Buf), VFS);
695  } else {
696  assert(Storage.getKind() == PCHStorage::Kind::InMemory);
697  // For in-memory preamble, we have to provide a VFS overlay that makes it
698  // accessible.
699  StringRef PCHPath = getInMemoryPreamblePath();
700  PreprocessorOpts.ImplicitPCHInclude = PCHPath;
701 
702  auto Buf = llvm::MemoryBuffer::getMemBuffer(Storage.asMemory().Data);
703  VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(Buf), VFS);
704  }
705 }
706 
711  const MacroDirective *MD) {}
712 
714  return std::error_code(static_cast<int>(Error), BuildPreambleErrorCategory());
715 }
716 
717 const char *BuildPreambleErrorCategory::name() const noexcept {
718  return "build-preamble.error";
719 }
720 
721 std::string BuildPreambleErrorCategory::message(int condition) const {
722  switch (static_cast<BuildPreambleError>(condition)) {
724  return "Preamble is empty";
726  return "Could not create temporary file for PCH";
728  return "CreateTargetInfo() return null";
730  return "Could not create VFS Overlay";
732  return "BeginSourceFile() return an error";
734  return "Could not emit PCH";
735  }
736  llvm_unreachable("unexpected BuildPreambleError");
737 }
Describes the bounds (start, size) of the preamble and a flag required by PreprocessorOptions::Precom...
Definition: Lexer.h:59
Implements support for file system lookup, file system caching, and directory search management...
Definition: FileManager.h:116
time_t getModificationTime() const
Definition: FileManager.h:91
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the &#39;real&#39; file system, as seen by the operating system.
The translation unit is a prefix to a translation unit, and is not complete.
Definition: LangOptions.h:247
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
void addRemappedFile(StringRef From, StringRef To)
This interface provides a way to observe the actions of the preprocessor as it does its thing...
Definition: PPCallbacks.h:36
void AddImplicitPreamble(CompilerInvocation &CI, IntrusiveRefCntPtr< vfs::FileSystem > &VFS, llvm::MemoryBuffer *MainFileBuffer) const
Changes options inside CI to use PCH from this preamble.
The virtual file system interface.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:149
void HandleTranslationUnit(ASTContext &Ctx) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
Definition: GeneratePCH.cpp:40
static llvm::ErrorOr< PrecompiledPreamble > Build(const CompilerInvocation &Invocation, const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr< vfs::FileSystem > VFS, std::shared_ptr< PCHContainerOperations > PCHContainerOps, bool StoreInMemory, PreambleCallbacks &Callbacks)
Try to build PrecompiledPreamble for Invocation.
Definition: Format.h:1900
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:48
An in-memory file system.
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 ...
A file system that allows overlaying one AbstractFileSystem on top of another.
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
std::error_code make_error_code(BuildPreambleError Error)
FrontendOptions & getFrontendOpts()
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:147
bool RetainRemappedFileBuffers
Whether the compiler instance should retain (i.e., not free) the buffers associated with remapped fil...
The result of a status operation.
void Reset()
Reset the state of the diagnostic object to its initial configuration.
Definition: Diagnostic.cpp:113
FrontendOptions & getFrontendOpts()
bool PreambleEndsAtStartOfLine
Whether the preamble ends at the start of a new line.
Definition: Lexer.h:67
A set of callbacks to gather useful information while building a preamble.
StringRef Filename
Definition: Format.cpp:1345
const char * name() const noexcept override
PreambleBounds getBounds() const
PreambleBounds used to build the preamble.
bool CanReuse(const CompilerInvocation &Invocation, const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, vfs::FileSystem *VFS) const
Check whether PrecompiledPreamble can be reused for the new contents(MainFileBuffer) of the main file...
static PreambleBounds ComputePreamble(StringRef Buffer, const LangOptions &LangOpts, unsigned MaxLines=0)
Compute the preamble of the given file.
Definition: Lexer.cpp:573
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
const FunctionProtoType * T
IntrusiveRefCntPtr< vfs::FileSystem > createVFSFromCompilerInvocation(const CompilerInvocation &CI, DiagnosticsEngine &Diags)
virtual void HandleMacroDefined(const Token &MacroNameTok, const MacroDirective *MD)
Called for each macro defined in the Preamble.
static TargetInfo * CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr< TargetOptions > &Opts)
Construct a target for the given options.
Definition: Targets.cpp:583
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.
Encapsulates changes to the "macros namespace" (the location where the macro name became active...
Definition: MacroInfo.h:291
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
StringRef getName() const
Definition: FileManager.h:84
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
LLVM IR: we accept this so that we can run the optimizer on it, and compile it to assembly or object ...
std::vector< FrontendInputFile > Inputs
The input files and their types.
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:59
llvm::sys::TimePoint getLastModificationTime() const
void ProcessWarningOptions(DiagnosticsEngine &Diags, const DiagnosticOptions &Opts, bool ReportDiags=true)
ProcessWarningOptions - Initialize the diagnostic client and process the warning options specified on...
Definition: Warnings.cpp:44
Abstract base class to use for AST consumer-based frontend actions.
virtual void AfterPCHEmitted(ASTWriter &Writer)
Called after PCH has been emitted.
llvm::MemoryBuffer * getMemoryBufferForFile(const FileEntry *File, bool *Invalid=nullptr)
Retrieve the memory buffer associated with the given file.
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()
off_t getSize() const
Definition: FileManager.h:87
uint64_t getSize() const
FileID getMainFileID() const
Returns the FileID of the main source file.
Helper class for holding the data necessary to invoke the compiler.
Defines the virtual file system interface vfs::FileSystem.
FrontendOptions - Options for controlling the behavior of the frontend.
virtual void AfterExecute(CompilerInstance &CI)
Called after FrontendAction::Execute(), but before FrontendAction::EndSourceFile().
unsigned Size
Size of the preamble in bytes.
Definition: Lexer.h:61
llvm::sys::fs::UniqueID getUniqueID() const
Generate pre-compiled header.
Preprocessor & getPreprocessor() const
Return the current preprocessor.
TranslationUnitKind
Describes the kind of translation unit being processed.
Definition: LangOptions.h:242
Writes an AST file containing the contents of a translation unit.
Definition: ASTWriter.h:104
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)
Definition: DeclBase.cpp:915
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...
Definition: ASTWriter.h:965
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.
#define true
Definition: stdbool.h:32
virtual void HandleTopLevelDecl(DeclGroupRef DG)
Called for each TopLevelDecl.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Definition: Preprocessor.h:908
This class handles loading and caching of source files into memory.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:127