diff options
Diffstat (limited to 'lib/Lex/PPDirectives.cpp')
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 391 |
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, |