jansvoboda11 created this revision.
jansvoboda11 added a reviewer: ahoppen.
jansvoboda11 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The `const DirectoryLookup *` out-parameter of 
`{HeaderSearch,Preprocessor}::LookupFile()` is assigned the most recently used 
search directory, which callers use to implement `#include_next`.

>From the function signature it's not obvious the `const DirectoryLookup *` is 
>being used as an iterator. This patch introduces `DirectoryLookupIterator` to 
>make that affordance obvious. This would've prevented a bug that occurred 
>after initially landing D116750 <https://reviews.llvm.org/D116750>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D117566

Files:
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/Lex/HeaderSearch.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/PPMacroExpansion.cpp

Index: clang/lib/Lex/PPMacroExpansion.cpp
===================================================================
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ 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,
+                                     DirectoryLookupIterator 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();
+  DirectoryLookupIterator 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,
Index: clang/lib/Lex/PPLexerChange.cpp
===================================================================
--- clang/lib/Lex/PPLexerChange.cpp
+++ 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, DirectoryLookupIterator 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) {
+                                            DirectoryLookupIterator CurDir) {
 
   // Add the current lexer to the include stack.
   if (CurPPLexer || CurTokenLexer)
Index: clang/lib/Lex/PPDirectives.cpp
===================================================================
--- clang/lib/Lex/PPDirectives.cpp
+++ clang/lib/Lex/PPDirectives.cpp
@@ -817,13 +817,13 @@
 
 Optional<FileEntryRef> Preprocessor::LookupFile(
     SourceLocation FilenameLoc, StringRef Filename, bool isAngled,
-    const DirectoryLookup *FromDir, const FileEntry *FromFile,
-    const DirectoryLookup **CurDirArg, SmallVectorImpl<char> *SearchPath,
+    DirectoryLookupIterator FromDir, const FileEntry *FromFile,
+    DirectoryLookupIterator *CurDirArg, SmallVectorImpl<char> *SearchPath,
     SmallVectorImpl<char> *RelativePath,
     ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped,
     bool *IsFrameworkFound, bool SkipCache) {
-  const DirectoryLookup *CurDirLocal = nullptr;
-  const DirectoryLookup *&CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
+  DirectoryLookupIterator CurDirLocal = nullptr;
+  DirectoryLookupIterator &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;
+    DirectoryLookupIterator TmpCurDir = CurDir;
+    DirectoryLookupIterator TmpFromDir = nullptr;
     while (Optional<FileEntryRef> 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,
+                                          DirectoryLookupIterator LookupFrom,
                                           const FileEntry *LookupFromFile) {
   Token FilenameTok;
   if (LexHeaderName(FilenameTok))
@@ -1830,10 +1830,10 @@
 }
 
 Optional<FileEntryRef> Preprocessor::LookupHeaderIncludeOrImport(
-    const DirectoryLookup **CurDir, StringRef& Filename,
+    DirectoryLookupIterator *CurDir, StringRef& Filename,
     SourceLocation FilenameLoc, CharSourceRange FilenameRange,
     const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl,
-    bool &IsMapped, const DirectoryLookup *LookupFrom,
+    bool &IsMapped, DirectoryLookupIterator LookupFrom,
     const FileEntry *LookupFromFile, StringRef& LookupFilename,
     SmallVectorImpl<char> &RelativePath, SmallVectorImpl<char> &SearchPath,
     ModuleMap::KnownHeader &SuggestedModule, bool isAngled) {
@@ -1960,7 +1960,7 @@
 ///        lookup.
 Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
     SourceLocation HashLoc, Token &IncludeTok, Token &FilenameTok,
-    SourceLocation EndLoc, const DirectoryLookup *LookupFrom,
+    SourceLocation EndLoc, DirectoryLookupIterator 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;
+  DirectoryLookupIterator 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;
+  DirectoryLookupIterator 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,
Index: clang/lib/Lex/HeaderSearch.cpp
===================================================================
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -831,14 +831,14 @@
 /// search is needed. Microsoft mode will pass all \#including files.
 Optional<FileEntryRef> HeaderSearch::LookupFile(
     StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
-    const DirectoryLookup *FromDir, const DirectoryLookup **CurDirArg,
+    DirectoryLookupIterator FromDir, DirectoryLookupIterator *CurDirArg,
     ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
     SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
     Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
     bool *IsMapped, bool *IsFrameworkFound, bool SkipCache,
     bool BuildSystemModule) {
-  const DirectoryLookup *CurDirLocal = nullptr;
-  const DirectoryLookup *&CurDir = CurDirArg ? *CurDirArg : CurDirLocal;
+  DirectoryLookupIterator CurDirLocal = nullptr;
+  DirectoryLookupIterator &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 - DirectoryLookupIterator(&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 = DirectoryLookupIterator(&SearchDirs[i]);
 
     // This file is a system header or C++ unfriendly if the dir is.
     HeaderFileInfo &HFI = getFileInfo(&File->getFileEntry());
Index: clang/include/clang/Lex/Preprocessor.h
===================================================================
--- clang/include/clang/Lex/Preprocessor.h
+++ 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;
+  DirectoryLookupIterator CurDirLookup = nullptr;
 
   /// The current macro we are expanding, if we are expanding a macro.
   ///
@@ -543,7 +543,7 @@
     std::unique_ptr<Lexer>      TheLexer;
     PreprocessorLexer          *ThePPLexer;
     std::unique_ptr<TokenLexer> TheTokenLexer;
-    const DirectoryLookup      *TheDirLookup;
+    DirectoryLookupIterator     TheDirLookup;
 
     // The following constructors are completely useless copies of the default
     // versions, only needed to pacify MSVC.
@@ -551,7 +551,7 @@
                      std::unique_ptr<Lexer> &&TheLexer,
                      PreprocessorLexer *ThePPLexer,
                      std::unique_ptr<TokenLexer> &&TheTokenLexer,
-                     const DirectoryLookup *TheDirLookup)
+                     DirectoryLookupIterator TheDirLookup)
         : CurLexerKind(std::move(CurLexerKind)),
           TheSubmodule(std::move(TheSubmodule)), TheLexer(std::move(TheLexer)),
           ThePPLexer(std::move(ThePPLexer)),
@@ -1367,7 +1367,7 @@
   /// 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,
+  bool EnterSourceFile(FileID FID, DirectoryLookupIterator Dir,
                        SourceLocation Loc, bool IsFirstIncludeOfFile = true);
 
   /// Add a Macro to the top of the include stack and start lexing
@@ -2050,8 +2050,8 @@
   /// reference is for system \#include's or not (i.e. using <> instead of "").
   Optional<FileEntryRef>
   LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled,
-             const DirectoryLookup *FromDir, const FileEntry *FromFile,
-             const DirectoryLookup **CurDir, SmallVectorImpl<char> *SearchPath,
+             DirectoryLookupIterator FromDir, const FileEntry *FromFile,
+             DirectoryLookupIterator *CurDir, SmallVectorImpl<char> *SearchPath,
              SmallVectorImpl<char> *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; }
+  DirectoryLookupIterator 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, DirectoryLookupIterator Dir);
 
   /// Set the FileID for the preprocessor predefines.
   void setPredefinesFileID(FileID FID) {
@@ -2300,22 +2300,22 @@
   };
 
   Optional<FileEntryRef> LookupHeaderIncludeOrImport(
-      const DirectoryLookup **CurDir, StringRef &Filename,
+      DirectoryLookupIterator *CurDir, StringRef &Filename,
       SourceLocation FilenameLoc, CharSourceRange FilenameRange,
       const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl,
-      bool &IsMapped, const DirectoryLookup *LookupFrom,
+      bool &IsMapped, DirectoryLookupIterator LookupFrom,
       const FileEntry *LookupFromFile, StringRef &LookupFilename,
       SmallVectorImpl<char> &RelativePath, SmallVectorImpl<char> &SearchPath,
       ModuleMap::KnownHeader &SuggestedModule, bool isAngled);
 
   // File inclusion.
   void HandleIncludeDirective(SourceLocation HashLoc, Token &Tok,
-                              const DirectoryLookup *LookupFrom = nullptr,
+                              DirectoryLookupIterator LookupFrom = nullptr,
                               const FileEntry *LookupFromFile = nullptr);
   ImportAction
   HandleHeaderIncludeOrImport(SourceLocation HashLoc, Token &IncludeTok,
                               Token &FilenameTok, SourceLocation EndLoc,
-                              const DirectoryLookup *LookupFrom = nullptr,
+                              DirectoryLookupIterator LookupFrom = nullptr,
                               const FileEntry *LookupFromFile = nullptr);
   void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok);
   void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok);
Index: clang/include/clang/Lex/HeaderSearch.h
===================================================================
--- clang/include/clang/Lex/HeaderSearch.h
+++ 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,64 @@
   bool IsUserSpecifiedSystemFramework;
 };
 
+/// A random access iterator over DirectoryLookup entries of HeaderSearch.
+struct DirectoryLookupIterator
+    : llvm::iterator_facade_base<DirectoryLookupIterator,
+                                 std::random_access_iterator_tag,
+                                 const DirectoryLookup> {
+  DirectoryLookupIterator(const DirectoryLookupIterator &) = default;
+
+  DirectoryLookupIterator &operator=(const DirectoryLookupIterator &) = default;
+
+  bool operator==(const DirectoryLookupIterator &RHS) const {
+    assert(*this && RHS && "Invalid iterators.");
+    return DL == RHS.DL;
+  }
+
+  bool operator<(const DirectoryLookupIterator &RHS) const {
+    assert(*this && RHS && "Invalid iterators.");
+    return DL < RHS.DL;
+  }
+
+  std::ptrdiff_t operator-(const DirectoryLookupIterator &RHS) const {
+    assert(*this && RHS && "Invalid iterators.");
+    return DL - RHS.DL;
+  }
+
+  DirectoryLookupIterator &operator+=(std::ptrdiff_t N) {
+    assert(*this && "Invalid iterator.");
+    DL += N;
+    return *this;
+  }
+
+  DirectoryLookupIterator &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.
+  DirectoryLookupIterator(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 DirectoryLookupIterator(const DirectoryLookup *DL) : DL(DL) {}
+
+  /// Only HeaderSearch is allowed to instantiate valid references.
+  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 +467,7 @@
   /// found.
   Optional<FileEntryRef> LookupFile(
       StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
-      const DirectoryLookup *FromDir, const DirectoryLookup **CurDir,
+      DirectoryLookupIterator FromDir, DirectoryLookupIterator *CurDir,
       ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
       SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
       Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D117566: [clang][lex] ... Jan Svoboda via Phabricator via cfe-commits

Reply via email to