diff options
author | Erich Keane <erich.keane@intel.com> | 2018-07-05 17:22:13 +0000 |
---|---|---|
committer | Erich Keane <erich.keane@intel.com> | 2018-07-05 17:22:13 +0000 |
commit | 76675de15cfc0912cb1b3520ec59768d96d501d2 (patch) | |
tree | aae9ab01ade7645e1ab82c66a7d0aebf0deeca33 /clang/lib/Lex/Preprocessor.cpp | |
parent | a8db71f06fd9cd37ebcf154efe38b0e2d4e4034b (diff) | |
download | bcm5719-llvm-76675de15cfc0912cb1b3520ec59768d96d501d2.tar.gz bcm5719-llvm-76675de15cfc0912cb1b3520ec59768d96d501d2.zip |
[clang-cl, PCH] Implement support for MS-style PCH through headers
Implement support for MS-style PCH through headers.
This enables support for /Yc and /Yu where the through header is either
on the command line or included in the source. It replaces the current
support the requires the header also be specified with /FI.
This change adds a -cc1 option -pch-through-header that is used to either
start or stop compilation during PCH create or use.
When creating a PCH, the compilation ends after compilation of the through
header.
When using a PCH, tokens are skipped until after the through header is seen.
Patch By: mikerice
Differential Revision: https://reviews.llvm.org/D46652
llvm-svn: 336379
Diffstat (limited to 'clang/lib/Lex/Preprocessor.cpp')
-rw-r--r-- | clang/lib/Lex/Preprocessor.cpp | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 358103d43d3..0217a2e60ed 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -149,6 +149,11 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, Ident_AbnormalTermination = nullptr; } + // If using a PCH with a through header, start skipping tokens. + if (!this->PPOpts->PCHThroughHeader.empty() && + !this->PPOpts->ImplicitPCHInclude.empty()) + SkippingUntilPCHThroughHeader = true; + if (this->PPOpts->GeneratePreamble) PreambleConditionalStack.startRecording(); } @@ -551,6 +556,72 @@ void Preprocessor::EnterMainSourceFile() { // Start parsing the predefines. EnterSourceFile(FID, nullptr, SourceLocation()); + + if (!PPOpts->PCHThroughHeader.empty()) { + // Lookup and save the FileID for the through header. If it isn't found + // in the search path, it's a fatal error. + const DirectoryLookup *CurDir; + const FileEntry *File = LookupFile( + SourceLocation(), PPOpts->PCHThroughHeader, + /*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr, CurDir, + /*SearchPath=*/nullptr, /*RelativePath=*/nullptr, + /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr); + if (!File) { + Diag(SourceLocation(), diag::err_pp_through_header_not_found) + << PPOpts->PCHThroughHeader; + return; + } + setPCHThroughHeaderFileID( + SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User)); + } + + // Skip tokens from the Predefines and if needed the main file. + if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) + SkipTokensUntilPCHThroughHeader(); +} + +void Preprocessor::setPCHThroughHeaderFileID(FileID FID) { + assert(PCHThroughHeaderFileID.isInvalid() && + "PCHThroughHeaderFileID already set!"); + PCHThroughHeaderFileID = FID; +} + +bool Preprocessor::isPCHThroughHeader(const FileEntry *FE) { + assert(PCHThroughHeaderFileID.isValid() && + "Invalid PCH through header FileID"); + return FE == SourceMgr.getFileEntryForID(PCHThroughHeaderFileID); +} + +bool Preprocessor::creatingPCHWithThroughHeader() { + return TUKind == TU_Prefix && !PPOpts->PCHThroughHeader.empty() && + PCHThroughHeaderFileID.isValid(); +} + +bool Preprocessor::usingPCHWithThroughHeader() { + return TUKind != TU_Prefix && !PPOpts->PCHThroughHeader.empty() && + PCHThroughHeaderFileID.isValid(); +} + +/// Skip tokens until after the #include of the through header. +/// Tokens in the predefines file and the main file may be skipped. If the end +/// of the predefines file is reached, skipping continues into the main file. +/// If the end of the main file is reached, it's a fatal error. +void Preprocessor::SkipTokensUntilPCHThroughHeader() { + bool ReachedMainFileEOF = false; + Token Tok; + while (true) { + bool InPredefines = (CurLexer->getFileID() == getPredefinesFileID()); + CurLexer->Lex(Tok); + if (Tok.is(tok::eof) && !InPredefines) { + ReachedMainFileEOF = true; + break; + } + if (!SkippingUntilPCHThroughHeader) + break; + } + if (ReachedMainFileEOF) + Diag(SourceLocation(), diag::err_pp_through_header_not_seen) + << PPOpts->PCHThroughHeader << 1; } void Preprocessor::replayPreambleConditionalStack() { |