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 (moveOnNoError(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 (moveOnNoError(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.