aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Lex/PPDirectives.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Lex/PPDirectives.cpp')
-rw-r--r--lib/Lex/PPDirectives.cpp391
1 files changed, 235 insertions, 156 deletions
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 2756042f23eb..3b7eaee3c914 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -33,6 +33,7 @@
#include "clang/Lex/Token.h"
#include "clang/Lex/VariadicMacroSupport.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
@@ -369,6 +370,37 @@ SourceLocation Preprocessor::CheckEndOfDirective(const char *DirType,
return DiscardUntilEndOfDirective().getEnd();
}
+Optional<unsigned> Preprocessor::getSkippedRangeForExcludedConditionalBlock(
+ SourceLocation HashLoc) {
+ if (!ExcludedConditionalDirectiveSkipMappings)
+ return None;
+ if (!HashLoc.isFileID())
+ return None;
+
+ std::pair<FileID, unsigned> HashFileOffset =
+ SourceMgr.getDecomposedLoc(HashLoc);
+ const llvm::MemoryBuffer *Buf = SourceMgr.getBuffer(HashFileOffset.first);
+ auto It = ExcludedConditionalDirectiveSkipMappings->find(Buf);
+ if (It == ExcludedConditionalDirectiveSkipMappings->end())
+ return None;
+
+ const PreprocessorSkippedRangeMapping &SkippedRanges = *It->getSecond();
+ // Check if the offset of '#' is mapped in the skipped ranges.
+ auto MappingIt = SkippedRanges.find(HashFileOffset.second);
+ if (MappingIt == SkippedRanges.end())
+ return None;
+
+ unsigned BytesToSkip = MappingIt->getSecond();
+ unsigned CurLexerBufferOffset = CurLexer->getCurrentBufferOffset();
+ assert(CurLexerBufferOffset >= HashFileOffset.second &&
+ "lexer is before the hash?");
+ // Take into account the fact that the lexer has already advanced, so the
+ // number of bytes to skip must be adjusted.
+ unsigned LengthDiff = CurLexerBufferOffset - HashFileOffset.second;
+ assert(BytesToSkip >= LengthDiff && "lexer is after the skipped range?");
+ return BytesToSkip - LengthDiff;
+}
+
/// SkipExcludedConditionalBlock - We just read a \#if or related directive and
/// decided that the subsequent tokens are in the \#if'd out portion of the
/// file. Lex the rest of the file, until we see an \#endif. If
@@ -395,6 +427,11 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
// disabling warnings, etc.
CurPPLexer->LexingRawMode = true;
Token Tok;
+ if (auto SkipLength =
+ getSkippedRangeForExcludedConditionalBlock(HashTokenLoc)) {
+ // Skip to the next '#endif' / '#else' / '#elif'.
+ CurLexer->skipOver(*SkipLength);
+ }
while (true) {
CurLexer->Lex(Tok);
@@ -678,7 +715,7 @@ Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
return nullptr;
}
-const FileEntry *Preprocessor::LookupFile(
+Optional<FileEntryRef> Preprocessor::LookupFile(
SourceLocation FilenameLoc, StringRef Filename, bool isAngled,
const DirectoryLookup *FromDir, const FileEntry *FromFile,
const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath,
@@ -715,7 +752,7 @@ const FileEntry *Preprocessor::LookupFile(
BuildSystemModule = getCurrentModule()->IsSystem;
} else if ((FileEnt =
SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())))
- Includers.push_back(std::make_pair(FileEnt, FileMgr.getDirectory(".")));
+ Includers.push_back(std::make_pair(FileEnt, *FileMgr.getDirectory(".")));
} else {
Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
}
@@ -739,7 +776,7 @@ const FileEntry *Preprocessor::LookupFile(
// the include path until we find that file or run out of files.
const DirectoryLookup *TmpCurDir = CurDir;
const DirectoryLookup *TmpFromDir = nullptr;
- while (const FileEntry *FE = HeaderInfo.LookupFile(
+ while (Optional<FileEntryRef> FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir,
Includers, SearchPath, RelativePath, RequestingModule,
SuggestedModule, /*IsMapped=*/nullptr,
@@ -747,7 +784,7 @@ const FileEntry *Preprocessor::LookupFile(
// Keep looking as if this file did a #include_next.
TmpFromDir = TmpCurDir;
++TmpFromDir;
- if (FE == FromFile) {
+ if (&FE->getFileEntry() == FromFile) {
// Found it.
FromDir = TmpFromDir;
CurDir = TmpCurDir;
@@ -757,7 +794,7 @@ const FileEntry *Preprocessor::LookupFile(
}
// Do a standard file entry lookup.
- const FileEntry *FE = HeaderInfo.LookupFile(
+ Optional<FileEntryRef> FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath,
RelativePath, RequestingModule, SuggestedModule, IsMapped,
IsFrameworkFound, SkipCache, BuildSystemModule);
@@ -765,7 +802,7 @@ const FileEntry *Preprocessor::LookupFile(
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,
- Filename, FE);
+ Filename, &FE->getFileEntry());
return FE;
}
@@ -775,14 +812,13 @@ const FileEntry *Preprocessor::LookupFile(
// headers on the #include stack and pass them to HeaderInfo.
if (IsFileLexer()) {
if ((CurFileEnt = CurPPLexer->getFileEntry())) {
- if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt,
- SearchPath, RelativePath,
- RequestingModule,
- SuggestedModule))) {
+ if (Optional<FileEntryRef> FE = HeaderInfo.LookupSubframeworkHeader(
+ Filename, CurFileEnt, SearchPath, RelativePath, RequestingModule,
+ SuggestedModule)) {
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,
- Filename, FE);
+ Filename, &FE->getFileEntry());
return FE;
}
}
@@ -791,13 +827,13 @@ const FileEntry *Preprocessor::LookupFile(
for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
if (IsFileLexer(ISEntry)) {
if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) {
- if ((FE = HeaderInfo.LookupSubframeworkHeader(
+ if (Optional<FileEntryRef> FE = HeaderInfo.LookupSubframeworkHeader(
Filename, CurFileEnt, SearchPath, RelativePath,
- RequestingModule, SuggestedModule))) {
+ RequestingModule, SuggestedModule)) {
if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
RequestingModule, RequestingModuleIsModuleInterface,
- FilenameLoc, Filename, FE);
+ FilenameLoc, Filename, &FE->getFileEntry());
return FE;
}
}
@@ -805,7 +841,7 @@ const FileEntry *Preprocessor::LookupFile(
}
// Otherwise, we really couldn't find the file.
- return nullptr;
+ return None;
}
//===----------------------------------------------------------------------===//
@@ -1022,7 +1058,7 @@ void Preprocessor::HandleDirective(Token &Result) {
// various pseudo-ops. Just return the # token and push back the following
// token to be lexed next time.
if (getLangOpts().AsmPreprocessor) {
- auto Toks = llvm::make_unique<Token[]>(2);
+ auto Toks = std::make_unique<Token[]>(2);
// Return the # and the token after it.
Toks[0] = SavedHash;
Toks[1] = Result;
@@ -1512,7 +1548,7 @@ void Preprocessor::EnterAnnotationToken(SourceRange Range,
void *AnnotationVal) {
// FIXME: Produce this as the current token directly, rather than
// allocating a new token for it.
- auto Tok = llvm::make_unique<Token[]>(1);
+ auto Tok = std::make_unique<Token[]>(1);
Tok[0].startToken();
Tok[0].setKind(Kind);
Tok[0].setLocation(Range.getBegin());
@@ -1675,6 +1711,133 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
}
}
+Optional<FileEntryRef> Preprocessor::LookupHeaderIncludeOrImport(
+ const DirectoryLookup *&CurDir, StringRef Filename,
+ SourceLocation FilenameLoc, CharSourceRange FilenameRange,
+ const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl,
+ bool &IsMapped, const DirectoryLookup *LookupFrom,
+ const FileEntry *LookupFromFile, StringRef LookupFilename,
+ SmallVectorImpl<char> &RelativePath, SmallVectorImpl<char> &SearchPath,
+ ModuleMap::KnownHeader &SuggestedModule, bool isAngled) {
+ Optional<FileEntryRef> File = LookupFile(
+ FilenameLoc, LookupFilename,
+ isAngled, LookupFrom, LookupFromFile, CurDir,
+ Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
+ &SuggestedModule, &IsMapped, &IsFrameworkFound);
+ if (File)
+ return File;
+
+ if (Callbacks) {
+ // Give the clients a chance to recover.
+ SmallString<128> RecoveryPath;
+ if (Callbacks->FileNotFound(Filename, RecoveryPath)) {
+ if (auto DE = FileMgr.getOptionalDirectoryRef(RecoveryPath)) {
+ // Add the recovery path to the list of search paths.
+ DirectoryLookup DL(*DE, SrcMgr::C_User, false);
+ HeaderInfo.AddSearchPath(DL, isAngled);
+
+ // Try the lookup again, skipping the cache.
+ Optional<FileEntryRef> File = LookupFile(
+ FilenameLoc,
+ LookupFilename, isAngled,
+ LookupFrom, LookupFromFile, CurDir, nullptr, nullptr,
+ &SuggestedModule, &IsMapped, /*IsFrameworkFound=*/nullptr,
+ /*SkipCache*/ true);
+ if (File)
+ return File;
+ }
+ }
+ }
+
+ if (SuppressIncludeNotFoundError)
+ return None;
+
+ // If the file could not be located and it was included via angle
+ // brackets, we can attempt a lookup as though it were a quoted path to
+ // provide the user with a possible fixit.
+ if (isAngled) {
+ Optional<FileEntryRef> File = LookupFile(
+ FilenameLoc, LookupFilename,
+ false, LookupFrom, LookupFromFile, CurDir,
+ Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
+ &SuggestedModule, &IsMapped,
+ /*IsFrameworkFound=*/nullptr);
+ if (File) {
+ Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal)
+ << Filename << IsImportDecl
+ << FixItHint::CreateReplacement(FilenameRange,
+ "\"" + Filename.str() + "\"");
+ return File;
+ }
+ }
+
+ // Check for likely typos due to leading or trailing non-isAlphanumeric
+ // characters
+ StringRef OriginalFilename = Filename;
+ if (LangOpts.SpellChecking) {
+ // A heuristic to correct a typo file name by removing leading and
+ // trailing non-isAlphanumeric characters.
+ auto CorrectTypoFilename = [](llvm::StringRef Filename) {
+ Filename = Filename.drop_until(isAlphanumeric);
+ while (!Filename.empty() && !isAlphanumeric(Filename.back())) {
+ Filename = Filename.drop_back();
+ }
+ return Filename;
+ };
+ StringRef TypoCorrectionName = CorrectTypoFilename(Filename);
+
+#ifndef _WIN32
+ // Normalize slashes when compiling with -fms-extensions on non-Windows.
+ // This is unnecessary on Windows since the filesystem there handles
+ // backslashes.
+ SmallString<128> NormalizedTypoCorrectionPath;
+ if (LangOpts.MicrosoftExt) {
+ NormalizedTypoCorrectionPath = TypoCorrectionName;
+ llvm::sys::path::native(NormalizedTypoCorrectionPath);
+ TypoCorrectionName = NormalizedTypoCorrectionPath;
+ }
+#endif
+
+ Optional<FileEntryRef> File = LookupFile(
+ FilenameLoc, TypoCorrectionName, isAngled, LookupFrom, LookupFromFile,
+ CurDir, Callbacks ? &SearchPath : nullptr,
+ Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped,
+ /*IsFrameworkFound=*/nullptr);
+ if (File) {
+ auto Hint =
+ isAngled ? FixItHint::CreateReplacement(
+ FilenameRange, "<" + TypoCorrectionName.str() + ">")
+ : FixItHint::CreateReplacement(
+ FilenameRange, "\"" + TypoCorrectionName.str() + "\"");
+ Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
+ << OriginalFilename << TypoCorrectionName << Hint;
+ // We found the file, so set the Filename to the name after typo
+ // correction.
+ Filename = TypoCorrectionName;
+ return File;
+ }
+ }
+
+ // If the file is still not found, just go with the vanilla diagnostic
+ assert(!File.hasValue() && "expected missing file");
+ Diag(FilenameTok, diag::err_pp_file_not_found)
+ << OriginalFilename << FilenameRange;
+ if (IsFrameworkFound) {
+ size_t SlashPos = OriginalFilename.find('/');
+ assert(SlashPos != StringRef::npos &&
+ "Include with framework name should have '/' in the filename");
+ StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
+ FrameworkCacheEntry &CacheEntry =
+ HeaderInfo.LookupFrameworkCache(FrameworkName);
+ assert(CacheEntry.Directory && "Found framework should be in cache");
+ Diag(FilenameTok, diag::note_pp_framework_without_header)
+ << OriginalFilename.substr(SlashPos + 1) << FrameworkName
+ << CacheEntry.Directory->getName();
+ }
+
+ return None;
+}
+
/// Handle either a #include-like directive or an import declaration that names
/// a header file.
///
@@ -1710,12 +1873,12 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
SourceLocation StartLoc = IsImportDecl ? IncludeTok.getLocation() : HashLoc;
// Complain about attempts to #include files in an audit pragma.
- if (PragmaARCCFCodeAuditedLoc.isValid()) {
+ if (PragmaARCCFCodeAuditedInfo.second.isValid()) {
Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
- Diag(PragmaARCCFCodeAuditedLoc, diag::note_pragma_entered_here);
+ Diag(PragmaARCCFCodeAuditedInfo.second, diag::note_pragma_entered_here);
// Immediately leave the pragma.
- PragmaARCCFCodeAuditedLoc = SourceLocation();
+ PragmaARCCFCodeAuditedInfo = {nullptr, SourceLocation()};
}
// Complain about attempts to #include files in an assume-nonnull pragma.
@@ -1746,127 +1909,26 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
// the path.
ModuleMap::KnownHeader SuggestedModule;
SourceLocation FilenameLoc = FilenameTok.getLocation();
+ StringRef LookupFilename = Filename;
+
+#ifndef _WIN32
+ // Normalize slashes when compiling with -fms-extensions on non-Windows. This
+ // is unnecessary on Windows since the filesystem there handles backslashes.
SmallString<128> NormalizedPath;
- if (LangOpts.MSVCCompat) {
+ if (LangOpts.MicrosoftExt) {
NormalizedPath = Filename.str();
-#ifndef _WIN32
llvm::sys::path::native(NormalizedPath);
-#endif
+ LookupFilename = NormalizedPath;
}
- const FileEntry *File = LookupFile(
- FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename,
- isAngled, LookupFrom, LookupFromFile, CurDir,
- Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
- &SuggestedModule, &IsMapped, &IsFrameworkFound);
-
- if (!File) {
- if (Callbacks) {
- // Give the clients a chance to recover.
- SmallString<128> RecoveryPath;
- if (Callbacks->FileNotFound(Filename, RecoveryPath)) {
- if (const DirectoryEntry *DE = FileMgr.getDirectory(RecoveryPath)) {
- // Add the recovery path to the list of search paths.
- DirectoryLookup DL(DE, SrcMgr::C_User, false);
- HeaderInfo.AddSearchPath(DL, isAngled);
-
- // Try the lookup again, skipping the cache.
- File = LookupFile(
- FilenameLoc,
- LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
- LookupFrom, LookupFromFile, CurDir, nullptr, nullptr,
- &SuggestedModule, &IsMapped, /*IsFrameworkFound=*/nullptr,
- /*SkipCache*/ true);
- }
- }
- }
-
- if (!SuppressIncludeNotFoundError) {
- // If the file could not be located and it was included via angle
- // brackets, we can attempt a lookup as though it were a quoted path to
- // provide the user with a possible fixit.
- if (isAngled) {
- File = LookupFile(
- FilenameLoc,
- LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, false,
- LookupFrom, LookupFromFile, CurDir,
- Callbacks ? &SearchPath : nullptr,
- Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped,
- /*IsFrameworkFound=*/nullptr);
- if (File) {
- Diag(FilenameTok,
- diag::err_pp_file_not_found_angled_include_not_fatal)
- << Filename << IsImportDecl
- << FixItHint::CreateReplacement(FilenameRange,
- "\"" + Filename.str() + "\"");
- }
- }
-
- // Check for likely typos due to leading or trailing non-isAlphanumeric
- // characters
- StringRef OriginalFilename = Filename;
- if (LangOpts.SpellChecking && !File) {
- // A heuristic to correct a typo file name by removing leading and
- // trailing non-isAlphanumeric characters.
- auto CorrectTypoFilename = [](llvm::StringRef Filename) {
- Filename = Filename.drop_until(isAlphanumeric);
- while (!Filename.empty() && !isAlphanumeric(Filename.back())) {
- Filename = Filename.drop_back();
- }
- return Filename;
- };
- StringRef TypoCorrectionName = CorrectTypoFilename(Filename);
- SmallString<128> NormalizedTypoCorrectionPath;
- if (LangOpts.MSVCCompat) {
- NormalizedTypoCorrectionPath = TypoCorrectionName.str();
-#ifndef _WIN32
- llvm::sys::path::native(NormalizedTypoCorrectionPath);
#endif
- }
- File = LookupFile(
- FilenameLoc,
- LangOpts.MSVCCompat ? NormalizedTypoCorrectionPath.c_str()
- : TypoCorrectionName,
- isAngled, LookupFrom, LookupFromFile, CurDir,
- Callbacks ? &SearchPath : nullptr,
- Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped,
- /*IsFrameworkFound=*/nullptr);
- if (File) {
- auto Hint =
- isAngled
- ? FixItHint::CreateReplacement(
- FilenameRange, "<" + TypoCorrectionName.str() + ">")
- : FixItHint::CreateReplacement(
- FilenameRange, "\"" + TypoCorrectionName.str() + "\"");
- Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
- << OriginalFilename << TypoCorrectionName << Hint;
- // We found the file, so set the Filename to the name after typo
- // correction.
- Filename = TypoCorrectionName;
- }
- }
- // If the file is still not found, just go with the vanilla diagnostic
- if (!File) {
- Diag(FilenameTok, diag::err_pp_file_not_found) << OriginalFilename
- << FilenameRange;
- if (IsFrameworkFound) {
- size_t SlashPos = OriginalFilename.find('/');
- assert(SlashPos != StringRef::npos &&
- "Include with framework name should have '/' in the filename");
- StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
- FrameworkCacheEntry &CacheEntry =
- HeaderInfo.LookupFrameworkCache(FrameworkName);
- assert(CacheEntry.Directory && "Found framework should be in cache");
- Diag(FilenameTok, diag::note_pp_framework_without_header)
- << OriginalFilename.substr(SlashPos + 1) << FrameworkName
- << CacheEntry.Directory->getName();
- }
- }
- }
- }
+ Optional<FileEntryRef> File = LookupHeaderIncludeOrImport(
+ CurDir, Filename, FilenameLoc, FilenameRange, FilenameTok,
+ IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
+ LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) {
- if (isPCHThroughHeader(File))
+ if (File && isPCHThroughHeader(&File->getFileEntry()))
SkippingUntilPCHThroughHeader = false;
return {ImportAction::None};
}
@@ -1877,7 +1939,8 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
// some directives (e.g. #endif of a header guard) will never be seen.
// Since this will lead to confusing errors, avoid the inclusion.
if (File && PreambleConditionalStack.isRecording() &&
- SourceMgr.translateFile(File) == SourceMgr.getMainFileID()) {
+ SourceMgr.translateFile(&File->getFileEntry()) ==
+ SourceMgr.getMainFileID()) {
Diag(FilenameTok.getLocation(),
diag::err_pp_including_mainfile_in_preamble);
return {ImportAction::None};
@@ -1896,7 +1959,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
// include cycle. Don't enter already processed files again as it can lead to
// reaching the max allowed include depth again.
if (Action == Enter && HasReachedMaxIncludeDepth && File &&
- HeaderInfo.getFileInfo(File).NumIncludes)
+ HeaderInfo.getFileInfo(&File->getFileEntry()).NumIncludes)
Action = IncludeLimitReached;
// Determine whether we should try to import the module for this #include, if
@@ -1972,7 +2035,8 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
SrcMgr::CharacteristicKind FileCharacter =
SourceMgr.getFileCharacteristic(FilenameTok.getLocation());
if (File)
- FileCharacter = std::max(HeaderInfo.getFileDirFlavor(File), FileCharacter);
+ FileCharacter = std::max(HeaderInfo.getFileDirFlavor(&File->getFileEntry()),
+ FileCharacter);
// If this is a '#import' or an import-declaration, don't re-enter the file.
//
@@ -1986,8 +2050,8 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
// Ask HeaderInfo if we should enter this #include file. If not, #including
// this file will have no effect.
if (Action == Enter && File &&
- !HeaderInfo.ShouldEnterIncludeFile(*this, File, EnterOnce,
- getLangOpts().Modules,
+ !HeaderInfo.ShouldEnterIncludeFile(*this, &File->getFileEntry(),
+ EnterOnce, getLangOpts().Modules,
SuggestedModule.getModule())) {
// Even if we've already preprocessed this header once and know that we
// don't need to see its contents again, we still need to import it if it's
@@ -2003,12 +2067,11 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
// Notify the callback object that we've seen an inclusion directive.
// FIXME: Use a different callback for a pp-import?
Callbacks->InclusionDirective(
- HashLoc, IncludeTok,
- LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
- FilenameRange, File, SearchPath, RelativePath,
+ HashLoc, IncludeTok, LookupFilename, isAngled, FilenameRange,
+ File ? &File->getFileEntry() : nullptr, SearchPath, RelativePath,
Action == Import ? SuggestedModule.getModule() : nullptr,
FileCharacter);
- if (Action == Skip)
+ if (Action == Skip && File)
Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
}
@@ -2026,11 +2089,11 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
// Issue a diagnostic if the name of the file on disk has a different case
// than the one we're about to open.
const bool CheckIncludePathPortability =
- !IsMapped && File && !File->tryGetRealPathName().empty();
+ !IsMapped && !File->getFileEntry().tryGetRealPathName().empty();
if (CheckIncludePathPortability) {
- StringRef Name = LangOpts.MSVCCompat ? NormalizedPath.str() : Filename;
- StringRef RealPathName = File->tryGetRealPathName();
+ StringRef Name = LookupFilename;
+ StringRef RealPathName = File->getFileEntry().tryGetRealPathName();
SmallVector<StringRef, 16> Components(llvm::sys::path::begin(Name),
llvm::sys::path::end(Name));
@@ -2101,7 +2164,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
// position on the file where it will be included and after the expansions.
if (IncludePos.isMacroID())
IncludePos = SourceMgr.getExpansionRange(IncludePos).getEnd();
- FileID FID = SourceMgr.createFileID(File, IncludePos, FileCharacter);
+ FileID FID = SourceMgr.createFileID(*File, IncludePos, FileCharacter);
assert(FID.isValid() && "Expected valid file ID");
// If all is good, enter the new file!
@@ -2399,6 +2462,13 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
Token Tok;
LexUnexpandedToken(Tok);
+ // Ensure we consume the rest of the macro body if errors occur.
+ auto _ = llvm::make_scope_exit([&]() {
+ // The flag indicates if we are still waiting for 'eod'.
+ if (CurLexer->ParsingPreprocessorDirective)
+ DiscardUntilEndOfDirective();
+ });
+
// Used to un-poison and then re-poison identifiers of the __VA_ARGS__ ilk
// within their appropriate context.
VariadicMacroScopeGuard VariadicMacroScopeGuard(*this);
@@ -2420,12 +2490,8 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
} else if (Tok.is(tok::l_paren)) {
// This is a function-like macro definition. Read the argument list.
MI->setIsFunctionLike();
- if (ReadMacroParameterList(MI, LastTok)) {
- // Throw away the rest of the line.
- if (CurPPLexer->ParsingPreprocessorDirective)
- DiscardUntilEndOfDirective();
+ if (ReadMacroParameterList(MI, LastTok))
return nullptr;
- }
// If this is a definition of an ISO C/C++ variadic function-like macro (not
// using the GNU named varargs extension) inform our variadic scope guard
@@ -2723,7 +2789,8 @@ void Preprocessor::HandleDefineDirective(
// If we need warning for not using the macro, add its location in the
// warn-because-unused-macro set. If it gets used it will be removed from set.
if (getSourceManager().isInMainFile(MI->getDefinitionLoc()) &&
- !Diags->isIgnored(diag::pp_macro_not_used, MI->getDefinitionLoc())) {
+ !Diags->isIgnored(diag::pp_macro_not_used, MI->getDefinitionLoc()) &&
+ !MacroExpansionInDirectivesOverride) {
MI->setIsWarnIfUnused(true);
WarnUnusedMacroLocs.insert(MI->getDefinitionLoc());
}
@@ -2832,6 +2899,9 @@ void Preprocessor::HandleIfdefDirective(Token &Result,
Callbacks->Ifdef(DirectiveTok.getLocation(), MacroNameTok, MD);
}
+ bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
+ getSourceManager().isInMainFile(DirectiveTok.getLocation());
+
// Should we include the stuff contained by this directive?
if (PPOpts->SingleFileParseMode && !MI) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
@@ -2839,7 +2909,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result,
CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
/*wasskip*/false, /*foundnonskip*/false,
/*foundelse*/false);
- } else if (!MI == isIfndef) {
+ } else if (!MI == isIfndef || RetainExcludedCB) {
// Yes, remember that we are inside a conditional, then lex the next token.
CurPPLexer->pushConditionalLevel(DirectiveTok.getLocation(),
/*wasskip*/false, /*foundnonskip*/true,
@@ -2880,13 +2950,16 @@ void Preprocessor::HandleIfDirective(Token &IfToken,
IfToken.getLocation(), DER.ExprRange,
(ConditionalTrue ? PPCallbacks::CVK_True : PPCallbacks::CVK_False));
+ bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
+ getSourceManager().isInMainFile(IfToken.getLocation());
+
// Should we include the stuff contained by this directive?
if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
// the directive blocks.
CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false,
/*foundnonskip*/false, /*foundelse*/false);
- } else if (ConditionalTrue) {
+ } else if (ConditionalTrue || RetainExcludedCB) {
// Yes, remember that we are inside a conditional, then lex the next token.
CurPPLexer->pushConditionalLevel(IfToken.getLocation(), /*wasskip*/false,
/*foundnonskip*/true, /*foundelse*/false);
@@ -2948,7 +3021,10 @@ void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) {
if (Callbacks)
Callbacks->Else(Result.getLocation(), CI.IfLoc);
- if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) {
+ bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
+ getSourceManager().isInMainFile(Result.getLocation());
+
+ if ((PPOpts->SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
// the directive blocks.
CurPPLexer->pushConditionalLevel(CI.IfLoc, /*wasskip*/false,
@@ -2990,7 +3066,10 @@ void Preprocessor::HandleElifDirective(Token &ElifToken,
Callbacks->Elif(ElifToken.getLocation(), ConditionRange,
PPCallbacks::CVK_NotEvaluated, CI.IfLoc);
- if (PPOpts->SingleFileParseMode && !CI.FoundNonSkip) {
+ bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
+ getSourceManager().isInMainFile(ElifToken.getLocation());
+
+ if ((PPOpts->SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) {
// In 'single-file-parse mode' undefined identifiers trigger parsing of all
// the directive blocks.
CurPPLexer->pushConditionalLevel(ElifToken.getLocation(), /*wasskip*/false,