diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -47,6 +47,7 @@ class ExternalPreprocessorSource; class FileEntry; class FileManager; +class HeaderSearch; class HeaderSearchOptions; class IdentifierInfo; class LangOptions; @@ -163,6 +164,61 @@ bool IsUserSpecifiedSystemFramework; }; +/// A random access iterator over search directories of HeaderSearch. +struct SearchDirIterator + : llvm::iterator_facade_base { + SearchDirIterator(const SearchDirIterator &) = default; + + SearchDirIterator &operator=(const SearchDirIterator &) = default; + + bool operator==(const SearchDirIterator &RHS) const { return DL == RHS.DL; } + + bool operator<(const SearchDirIterator &RHS) const { + assert(*this && RHS && "Invalid iterators."); + return DL < RHS.DL; + } + + std::ptrdiff_t operator-(const SearchDirIterator &RHS) const { + assert(*this && RHS && "Invalid iterators."); + return DL - RHS.DL; + } + + SearchDirIterator &operator+=(std::ptrdiff_t N) { + assert(*this && "Invalid iterator."); + DL += N; + return *this; + } + + SearchDirIterator &operator-=(ptrdiff_t N) { + assert(*this && "Invalid iterator."); + DL -= N; + return *this; + } + + const DirectoryLookup &operator*() const { + assert(*this && "Invalid iterator."); + return *DL; + } + + /// Creates an invalid iterator. + SearchDirIterator(std::nullptr_t) : DL(nullptr) {} + + /// Checks whether the iterator is valid. + operator bool() const { return DL != nullptr; } + +private: + /// The current element. + const DirectoryLookup *DL; + + /// The constructor that creates a valid iterator. + explicit SearchDirIterator(const DirectoryLookup *DL) : DL(DL) {} + + /// Only HeaderSearch is allowed to instantiate valid iterators. + friend HeaderSearch; +}; + /// Encapsulates the information needed to find the file referenced /// by a \#include or \#include_next, (sub-)framework lookup, etc. class HeaderSearch { @@ -408,7 +464,7 @@ /// found. Optional LookupFile( StringRef Filename, SourceLocation IncludeLoc, bool isAngled, - const DirectoryLookup *FromDir, const DirectoryLookup **CurDir, + SearchDirIterator FromDir, SearchDirIterator *CurDir, ArrayRef> Includers, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -515,7 +515,7 @@ /// /// This allows us to implement \#include_next and find directory-specific /// properties. - const DirectoryLookup *CurDirLookup = nullptr; + SearchDirIterator CurDirLookup = nullptr; /// The current macro we are expanding, if we are expanding a macro. /// @@ -543,7 +543,7 @@ std::unique_ptr TheLexer; PreprocessorLexer *ThePPLexer; std::unique_ptr TheTokenLexer; - const DirectoryLookup *TheDirLookup; + SearchDirIterator TheDirLookup; // The following constructors are completely useless copies of the default // versions, only needed to pacify MSVC. @@ -551,7 +551,7 @@ std::unique_ptr &&TheLexer, PreprocessorLexer *ThePPLexer, std::unique_ptr &&TheTokenLexer, - const DirectoryLookup *TheDirLookup) + SearchDirIterator TheDirLookup) : CurLexerKind(std::move(CurLexerKind)), TheSubmodule(std::move(TheSubmodule)), TheLexer(std::move(TheLexer)), ThePPLexer(std::move(ThePPLexer)), @@ -1367,8 +1367,8 @@ /// start lexing tokens from it instead of the current buffer. /// /// Emits a diagnostic, doesn't enter the file, and returns true on error. - bool EnterSourceFile(FileID FID, const DirectoryLookup *Dir, - SourceLocation Loc, bool IsFirstIncludeOfFile = true); + bool EnterSourceFile(FileID FID, SearchDirIterator Dir, SourceLocation Loc, + bool IsFirstIncludeOfFile = true); /// Add a Macro to the top of the include stack and start lexing /// tokens from it instead of the current buffer. @@ -2050,8 +2050,8 @@ /// reference is for system \#include's or not (i.e. using <> instead of ""). Optional LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled, - const DirectoryLookup *FromDir, const FileEntry *FromFile, - const DirectoryLookup **CurDir, SmallVectorImpl *SearchPath, + SearchDirIterator FromDir, const FileEntry *FromFile, + SearchDirIterator *CurDir, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache = false); @@ -2061,7 +2061,7 @@ /// /// This allows us to implement \#include_next and find directory-specific /// properties. - const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; } + SearchDirIterator GetCurDirLookup() { return CurDirLookup; } /// Return true if we're in the top-level file, not in a \#include. bool isInPrimaryFile() const; @@ -2223,7 +2223,7 @@ /// Add a lexer to the top of the include stack and /// start lexing tokens from it instead of the current buffer. - void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir); + void EnterSourceFileWithLexer(Lexer *TheLexer, SearchDirIterator Dir); /// Set the FileID for the preprocessor predefines. void setPredefinesFileID(FileID FID) { @@ -2300,22 +2300,22 @@ }; Optional LookupHeaderIncludeOrImport( - const DirectoryLookup **CurDir, StringRef &Filename, + SearchDirIterator *CurDir, StringRef &Filename, SourceLocation FilenameLoc, CharSourceRange FilenameRange, const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl, - bool &IsMapped, const DirectoryLookup *LookupFrom, + bool &IsMapped, SearchDirIterator LookupFrom, const FileEntry *LookupFromFile, StringRef &LookupFilename, SmallVectorImpl &RelativePath, SmallVectorImpl &SearchPath, ModuleMap::KnownHeader &SuggestedModule, bool isAngled); // File inclusion. void HandleIncludeDirective(SourceLocation HashLoc, Token &Tok, - const DirectoryLookup *LookupFrom = nullptr, + SearchDirIterator LookupFrom = nullptr, const FileEntry *LookupFromFile = nullptr); ImportAction HandleHeaderIncludeOrImport(SourceLocation HashLoc, Token &IncludeTok, Token &FilenameTok, SourceLocation EndLoc, - const DirectoryLookup *LookupFrom = nullptr, + SearchDirIterator LookupFrom = nullptr, const FileEntry *LookupFromFile = nullptr); void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok); void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok); diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -831,14 +831,14 @@ /// search is needed. Microsoft mode will pass all \#including files. Optional HeaderSearch::LookupFile( StringRef Filename, SourceLocation IncludeLoc, bool isAngled, - const DirectoryLookup *FromDir, const DirectoryLookup **CurDirArg, + SearchDirIterator FromDir, SearchDirIterator *CurDirArg, ArrayRef> Includers, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache, bool BuildSystemModule) { - const DirectoryLookup *CurDirLocal = nullptr; - const DirectoryLookup *&CurDir = CurDirArg ? *CurDirArg : CurDirLocal; + SearchDirIterator CurDirLocal = nullptr; + SearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal; if (IsMapped) *IsMapped = false; @@ -966,7 +966,7 @@ // If this is a #include_next request, start searching after the directory the // file was found in. if (FromDir) - i = FromDir-&SearchDirs[0]; + i = FromDir - SearchDirIterator(&SearchDirs[0]); // Cache all of the lookups performed by this method. Many headers are // multiply included, and the "pragma once" optimization prevents them from @@ -1021,7 +1021,7 @@ if (!File) continue; - CurDir = &SearchDirs[i]; + CurDir = SearchDirIterator(&SearchDirs[i]); // This file is a system header or C++ unfriendly if the dir is. HeaderFileInfo &HFI = getFileInfo(&File->getFileEntry()); diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -817,13 +817,13 @@ Optional Preprocessor::LookupFile( SourceLocation FilenameLoc, StringRef Filename, bool isAngled, - const DirectoryLookup *FromDir, const FileEntry *FromFile, - const DirectoryLookup **CurDirArg, SmallVectorImpl *SearchPath, + SearchDirIterator FromDir, const FileEntry *FromFile, + SearchDirIterator *CurDirArg, SmallVectorImpl *SearchPath, SmallVectorImpl *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache) { - const DirectoryLookup *CurDirLocal = nullptr; - const DirectoryLookup *&CurDir = CurDirArg ? *CurDirArg : CurDirLocal; + SearchDirIterator CurDirLocal = nullptr; + SearchDirIterator &CurDir = CurDirArg ? *CurDirArg : CurDirLocal; Module *RequestingModule = getModuleForLocation(FilenameLoc); bool RequestingModuleIsModuleInterface = !SourceMgr.isInMainFile(FilenameLoc); @@ -877,8 +877,8 @@ if (FromFile) { // We're supposed to start looking from after a particular file. Search // the include path until we find that file or run out of files. - const DirectoryLookup *TmpCurDir = CurDir; - const DirectoryLookup *TmpFromDir = nullptr; + SearchDirIterator TmpCurDir = CurDir; + SearchDirIterator TmpFromDir = nullptr; while (Optional FE = HeaderInfo.LookupFile( Filename, FilenameLoc, isAngled, TmpFromDir, &TmpCurDir, Includers, SearchPath, RelativePath, RequestingModule, @@ -1785,7 +1785,7 @@ /// specifies the file to start searching from. void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, Token &IncludeTok, - const DirectoryLookup *LookupFrom, + SearchDirIterator LookupFrom, const FileEntry *LookupFromFile) { Token FilenameTok; if (LexHeaderName(FilenameTok)) @@ -1830,13 +1830,13 @@ } Optional 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 &RelativePath, SmallVectorImpl &SearchPath, - ModuleMap::KnownHeader &SuggestedModule, bool isAngled) { + SearchDirIterator *CurDir, StringRef &Filename, SourceLocation FilenameLoc, + CharSourceRange FilenameRange, const Token &FilenameTok, + bool &IsFrameworkFound, bool IsImportDecl, bool &IsMapped, + SearchDirIterator LookupFrom, const FileEntry *LookupFromFile, + StringRef &LookupFilename, SmallVectorImpl &RelativePath, + SmallVectorImpl &SearchPath, ModuleMap::KnownHeader &SuggestedModule, + bool isAngled) { Optional File = LookupFile( FilenameLoc, LookupFilename, isAngled, LookupFrom, LookupFromFile, CurDir, @@ -1960,7 +1960,7 @@ /// lookup. Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( SourceLocation HashLoc, Token &IncludeTok, Token &FilenameTok, - SourceLocation EndLoc, const DirectoryLookup *LookupFrom, + SourceLocation EndLoc, SearchDirIterator LookupFrom, const FileEntry *LookupFromFile) { SmallString<128> FilenameBuffer; StringRef Filename = getSpelling(FilenameTok, FilenameBuffer); @@ -2010,7 +2010,7 @@ // Search include directories. bool IsMapped = false; bool IsFrameworkFound = false; - const DirectoryLookup *CurDir; + SearchDirIterator CurDir = nullptr; SmallString<1024> SearchPath; SmallString<1024> RelativePath; // We get the raw path only if we have 'Callbacks' to which we later pass @@ -2400,7 +2400,7 @@ // #include_next is like #include, except that we start searching after // the current found directory. If we can't do this, issue a // diagnostic. - const DirectoryLookup *Lookup = CurDirLookup; + SearchDirIterator Lookup = CurDirLookup; const FileEntry *LookupFromFile = nullptr; if (isInPrimaryFile() && LangOpts.IsHeaderFile) { // If the main file is a header, then it's either for PCH/AST generation, diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -66,7 +66,7 @@ /// EnterSourceFile - Add a source file to the top of the include stack and /// start lexing tokens from it instead of the current buffer. -bool Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir, +bool Preprocessor::EnterSourceFile(FileID FID, SearchDirIterator CurDir, SourceLocation Loc, bool IsFirstIncludeOfFile) { assert(!CurTokenLexer && "Cannot #include a file inside a macro!"); @@ -100,7 +100,7 @@ /// EnterSourceFileWithLexer - Add a source file to the top of the include stack /// and start lexing tokens from it instead of the current buffer. void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, - const DirectoryLookup *CurDir) { + SearchDirIterator CurDir) { // Add the current lexer to the include stack. if (CurPPLexer || CurTokenLexer) diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1157,9 +1157,9 @@ /// EvaluateHasIncludeCommon - Process a '__has_include("path")' /// or '__has_include_next("path")' expression. /// Returns true if successful. -static bool EvaluateHasIncludeCommon(Token &Tok, - IdentifierInfo *II, Preprocessor &PP, - const DirectoryLookup *LookupFrom, +static bool EvaluateHasIncludeCommon(Token &Tok, IdentifierInfo *II, + Preprocessor &PP, + SearchDirIterator LookupFrom, const FileEntry *LookupFromFile) { // Save the location of the current token. If a '(' is later found, use // that location. If not, use the end of this location instead. @@ -1260,7 +1260,7 @@ // issue a diagnostic. // FIXME: Factor out duplication with // Preprocessor::HandleIncludeNextDirective. - const DirectoryLookup *Lookup = PP.GetCurDirLookup(); + SearchDirIterator Lookup = PP.GetCurDirLookup(); const FileEntry *LookupFromFile = nullptr; if (PP.isInPrimaryFile() && PP.getLangOpts().IsHeaderFile) { // If the main file is a header, then it's either for PCH/AST generation,