[VFS] vfs::directory_iterator yields path and file type instead of full Status
authorSam McCall <sam.mccall@gmail.com>
Fri, 14 Sep 2018 12:47:38 +0000 (12:47 +0000)
committerSam McCall <sam.mccall@gmail.com>
Fri, 14 Sep 2018 12:47:38 +0000 (12:47 +0000)
Summary:
Most callers I can find are using only `getName()`. Type is used by the
recursive iterator.

Now we don't have to call stat() on every listed file (on most platforms).
Exceptions are e.g. Solaris where readdir() doesn't include type information.
On those platforms we'll still stat() - see D51918.

The result is significantly faster (stat() can be slow).
My motivation: this may allow us to improve clang IO on large TUs with long
include search paths. Caching readdir() results may allow us to skip many stat()
and open() operations on nonexistent files.

Reviewers: bkramer

Subscribers: fedor.sergeev, cfe-commits

Differential Revision: https://reviews.llvm.org/D51921

llvm-svn: 342232

clang/include/clang/Basic/VirtualFileSystem.h
clang/lib/Basic/VirtualFileSystem.cpp
clang/lib/Driver/ToolChains/BareMetal.cpp
clang/lib/Driver/ToolChains/Gnu.cpp
clang/lib/Frontend/CompilerInstance.cpp
clang/lib/Frontend/FrontendAction.cpp
clang/lib/Lex/HeaderSearch.cpp
clang/lib/Lex/ModuleMap.cpp
clang/lib/Lex/PPLexerChange.cpp
clang/unittests/Basic/VirtualFileSystemTest.cpp

index c808e90..fe660cc 100644 (file)
@@ -126,6 +126,21 @@ public:
   virtual std::error_code close() = 0;
 };
 
+/// A member of a directory, yielded by a directory_iterator.
+/// Only information available on most platforms is included.
+class directory_entry {
+  std::string Path;
+  llvm::sys::fs::file_type Type;
+
+public:
+  directory_entry() = default;
+  directory_entry(std::string Path, llvm::sys::fs::file_type Type)
+      : Path(std::move(Path)), Type(Type) {}
+
+  llvm::StringRef path() const { return Path; }
+  llvm::sys::fs::file_type type() const { return Type; }
+};
+
 namespace detail {
 
 /// An interface for virtual file systems to provide an iterator over the
@@ -134,10 +149,10 @@ struct DirIterImpl {
   virtual ~DirIterImpl();
 
   /// Sets \c CurrentEntry to the next entry in the directory on success,
-  /// or returns a system-defined \c error_code.
+  /// to directory_entry() at end,  or returns a system-defined \c error_code.
   virtual std::error_code increment() = 0;
 
-  Status CurrentEntry;
+  directory_entry CurrentEntry;
 };
 
 } // namespace detail
@@ -151,7 +166,7 @@ public:
   directory_iterator(std::shared_ptr<detail::DirIterImpl> I)
       : Impl(std::move(I)) {
     assert(Impl.get() != nullptr && "requires non-null implementation");
-    if (!Impl->CurrentEntry.isStatusKnown())
+    if (Impl->CurrentEntry.path().empty())
       Impl.reset(); // Normalize the end iterator to Impl == nullptr.
   }
 
@@ -162,17 +177,17 @@ public:
   directory_iterator &increment(std::error_code &EC) {
     assert(Impl && "attempting to increment past end");
     EC = Impl->increment();
-    if (!Impl->CurrentEntry.isStatusKnown())
+    if (Impl->CurrentEntry.path().empty())
       Impl.reset(); // Normalize the end iterator to Impl == nullptr.
     return *this;
   }
 
-  const Status &operator*() const { return Impl->CurrentEntry; }
-  const Status *operator->() const { return &Impl->CurrentEntry; }
+  const directory_entry &operator*() const { return Impl->CurrentEntry; }
+  const directory_entry *operator->() const { return &Impl->CurrentEntry; }
 
   bool operator==(const directory_iterator &RHS) const {
     if (Impl && RHS.Impl)
-      return Impl->CurrentEntry.equivalent(RHS.Impl->CurrentEntry);
+      return Impl->CurrentEntry.path() == RHS.Impl->CurrentEntry.path();
     return !Impl && !RHS.Impl;
   }
   bool operator!=(const directory_iterator &RHS) const {
@@ -201,8 +216,8 @@ public:
   /// Equivalent to operator++, with an error code.
   recursive_directory_iterator &increment(std::error_code &EC);
 
-  const Status &operator*() const { return *State->top(); }
-  const Status *operator->() const { return &*State->top(); }
+  const directory_entry &operator*() const { return *State->top(); }
+  const directory_entry *operator->() const { return &*State->top(); }
 
   bool operator==(const recursive_directory_iterator &Other) const {
     return State == Other.State; // identity
index 9972ac4..e5eb5e4 100644 (file)
@@ -315,27 +315,16 @@ class RealFSDirIter : public clang::vfs::detail::DirIterImpl {
 
 public:
   RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
-    if (Iter != llvm::sys::fs::directory_iterator()) {
-      llvm::sys::fs::file_status S;
-      std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true);
-      CurrentEntry = Status::copyWithNewName(S, Iter->path());
-      if (!EC)
-        EC = ErrorCode;
-    }
+    if (Iter != llvm::sys::fs::directory_iterator())
+      CurrentEntry = directory_entry(Iter->path(), Iter->type());
   }
 
   std::error_code increment() override {
     std::error_code EC;
     Iter.increment(EC);
-    if (Iter == llvm::sys::fs::directory_iterator()) {
-      CurrentEntry = Status();
-    } else {
-      llvm::sys::fs::file_status S;
-      std::error_code ErrorCode = llvm::sys::fs::status(Iter->path(), S, true);
-      CurrentEntry = Status::copyWithNewName(S, Iter->path());
-      if (!EC)
-        EC = ErrorCode;
-    }
+    CurrentEntry = (Iter == llvm::sys::fs::directory_iterator())
+                       ? directory_entry()
+                       : directory_entry(Iter->path(), Iter->type());
     return EC;
   }
 };
@@ -446,11 +435,11 @@ class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl {
     while (true) {
       std::error_code EC = incrementDirIter(IsFirstTime);
       if (EC || CurrentDirIter == directory_iterator()) {
-        CurrentEntry = Status();
+        CurrentEntry = directory_entry();
         return EC;
       }
       CurrentEntry = *CurrentDirIter;
-      StringRef Name = llvm::sys::path::filename(CurrentEntry.getName());
+      StringRef Name = llvm::sys::path::filename(CurrentEntry.path());
       if (SeenNames.insert(Name).second)
         return EC; // name not seen before
     }
@@ -850,11 +839,21 @@ class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl {
     if (I != E) {
       SmallString<256> Path(RequestedDirName);
       llvm::sys::path::append(Path, I->second->getFileName());
-      CurrentEntry = detail::getNodeStatus(I->second.get(), Path);
+      sys::fs::file_type Type;
+      switch (I->second->getKind()) {
+        case detail::IME_File:
+        case detail::IME_HardLink:
+          Type = sys::fs::file_type::regular_file;
+          break;
+        case detail::IME_Directory:
+          Type = sys::fs::file_type::directory_file;
+          break;
+      }
+      CurrentEntry = directory_entry(Path.str(), Type);
     } else {
       // When we're at the end, make CurrentEntry invalid and DirIterImpl will
       // do the rest.
-      CurrentEntry = Status();
+      CurrentEntry = directory_entry();
     }
   }
 
@@ -1010,17 +1009,14 @@ public:
   static bool classof(const Entry *E) { return E->getKind() == EK_File; }
 };
 
-class RedirectingFileSystem;
-
 class VFSFromYamlDirIterImpl : public clang::vfs::detail::DirIterImpl {
   std::string Dir;
-  RedirectingFileSystem &FS;
   RedirectingDirectoryEntry::iterator Current, End;
 
   std::error_code incrementImpl();
 
 public:
-  VFSFromYamlDirIterImpl(const Twine &Path, RedirectingFileSystem &FS,
+  VFSFromYamlDirIterImpl(const Twine &Path,
                          RedirectingDirectoryEntry::iterator Begin,
                          RedirectingDirectoryEntry::iterator End,
                          std::error_code &EC);
@@ -1184,8 +1180,8 @@ public:
     }
 
     auto *D = cast<RedirectingDirectoryEntry>(*E);
-    return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(Dir,
-        *this, D->contents_begin(), D->contents_end(), EC));
+    return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(
+        Dir, D->contents_begin(), D->contents_end(), EC));
   }
 
   void setExternalContentsPrefixDir(StringRef PrefixDir) {
@@ -2079,10 +2075,9 @@ void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
 }
 
 VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(
-    const Twine &_Path, RedirectingFileSystem &FS,
-    RedirectingDirectoryEntry::iterator Begin,
+    const Twine &_Path, RedirectingDirectoryEntry::iterator Begin,
     RedirectingDirectoryEntry::iterator End, std::error_code &EC)
-    : Dir(_Path.str()), FS(FS), Current(Begin), End(End) {
+    : Dir(_Path.str()), Current(Begin), End(End) {
   EC = incrementImpl();
 }
 
@@ -2096,23 +2091,21 @@ std::error_code VFSFromYamlDirIterImpl::incrementImpl() {
   while (Current != End) {
     SmallString<128> PathStr(Dir);
     llvm::sys::path::append(PathStr, (*Current)->getName());
-    llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
-    if (!S) {
-      // Skip entries which do not map to a reliable external content.
-      if (FS.ignoreNonExistentContents() &&
-          S.getError() == llvm::errc::no_such_file_or_directory) {
-        ++Current;
-        continue;
-      } else {
-        return S.getError();
-      }
+    sys::fs::file_type Type;
+    switch ((*Current)->getKind()) {
+      case EK_Directory:
+        Type = sys::fs::file_type::directory_file;
+        break;
+      case EK_File:
+        Type = sys::fs::file_type::regular_file;
+        break;
     }
-    CurrentEntry = *S;
+    CurrentEntry = directory_entry(PathStr.str(), Type);
     break;
   }
 
   if (Current == End)
-    CurrentEntry = Status();
+    CurrentEntry = directory_entry();
   return {};
 }
 
@@ -2130,10 +2123,10 @@ vfs::recursive_directory_iterator::recursive_directory_iterator(FileSystem &FS_,
 vfs::recursive_directory_iterator &
 recursive_directory_iterator::increment(std::error_code &EC) {
   assert(FS && State && !State->empty() && "incrementing past end");
-  assert(State->top()->isStatusKnown() && "non-canonical end iterator");
+  assert(!State->top()->path().empty() && "non-canonical end iterator");
   vfs::directory_iterator End;
-  if (State->top()->isDirectory()) {
-    vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC);
+  if (State->top()->type() == sys::fs::file_type::directory_file) {
+    vfs::directory_iterator I = FS->dir_begin(State->top()->path(), EC);
     if (I != End) {
       State->push(I);
       return *this;
index c302d64..adce108 100644 (file)
@@ -122,7 +122,7 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(
     for (vfs::directory_iterator LI =
            getDriver().getVFS().dir_begin(Dir.str(), EC), LE;
          !EC && LI != LE; LI = LI.increment(EC)) {
-      StringRef VersionText = llvm::sys::path::filename(LI->getName());
+      StringRef VersionText = llvm::sys::path::filename(LI->path());
       auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
       if (CandidateVersion.Major == -1)
         continue;
index 8911930..fda02b5 100644 (file)
@@ -1764,7 +1764,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
     std::error_code EC;
     for (vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC), LE;
          !EC && LI != LE; LI = LI.increment(EC)) {
-      StringRef VersionText = llvm::sys::path::filename(LI->getName());
+      StringRef VersionText = llvm::sys::path::filename(LI->path());
       GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
 
       // Filter out obviously bad entries.
@@ -2209,17 +2209,17 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
              LI = D.getVFS().dir_begin(LibDir + "/" + LibSuffix, EC),
              LE;
          !EC && LI != LE; LI = LI.increment(EC)) {
-      StringRef VersionText = llvm::sys::path::filename(LI->getName());
+      StringRef VersionText = llvm::sys::path::filename(LI->path());
       GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
       if (CandidateVersion.Major != -1) // Filter obviously bad entries.
-        if (!CandidateGCCInstallPaths.insert(LI->getName()).second)
+        if (!CandidateGCCInstallPaths.insert(LI->path()).second)
           continue; // Saw this path before; no need to look at it again.
       if (CandidateVersion.isOlderThan(4, 1, 1))
         continue;
       if (CandidateVersion <= Version)
         continue;
 
-      if (!ScanGCCForMultilibs(TargetTriple, Args, LI->getName(),
+      if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(),
                                NeedsBiarchSuffix))
         continue;
 
index f1a8720..38a09a0 100644 (file)
@@ -185,10 +185,10 @@ static void collectIncludePCH(CompilerInstance &CI,
     // used here since we're not interested in validating the PCH at this time,
     // but only to check whether this is a file containing an AST.
     if (!ASTReader::readASTFileControlBlock(
-            Dir->getName(), FileMgr, CI.getPCHContainerReader(),
+            Dir->path(), FileMgr, CI.getPCHContainerReader(),
             /*FindModuleFileExtensions=*/false, Validator,
             /*ValidateDiagnosticOptions=*/false))
-      MDC->addFile(Dir->getName());
+      MDC->addFile(Dir->path());
   }
 }
 
index 74550c4..ddb522a 100644 (file)
@@ -347,12 +347,12 @@ static std::error_code collectModuleHeaderIncludes(
          Dir != End && !EC; Dir.increment(EC)) {
       // Check whether this entry has an extension typically associated with
       // headers.
-      if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->getName()))
-          .Cases(".h", ".H", ".hh", ".hpp", true)
-          .Default(false))
+      if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
+               .Cases(".h", ".H", ".hh", ".hpp", true)
+               .Default(false))
         continue;
 
-      const FileEntry *Header = FileMgr.getFile(Dir->getName());
+      const FileEntry *Header = FileMgr.getFile(Dir->path());
       // FIXME: This shouldn't happen unless there is a file system race. Is
       // that worth diagnosing?
       if (!Header)
@@ -365,7 +365,7 @@ static std::error_code collectModuleHeaderIncludes(
 
       // Compute the relative path from the directory to this file.
       SmallVector<StringRef, 16> Components;
-      auto PathIt = llvm::sys::path::rbegin(Dir->getName());
+      auto PathIt = llvm::sys::path::rbegin(Dir->path());
       for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt)
         Components.push_back(*PathIt);
       SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten);
@@ -696,10 +696,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
            Dir != DirEnd && !EC; Dir.increment(EC)) {
         // Check whether this is an acceptable AST file.
         if (ASTReader::isAcceptableASTFile(
-                Dir->getName(), FileMgr, CI.getPCHContainerReader(),
+                Dir->path(), FileMgr, CI.getPCHContainerReader(),
                 CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(),
                 SpecificModuleCachePath)) {
-          PPOpts.ImplicitPCHInclude = Dir->getName();
+          PPOpts.ImplicitPCHInclude = Dir->path();
           Found = true;
           break;
         }
index 2ab020f..99b9cce 100644 (file)
@@ -1574,17 +1574,17 @@ void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
         vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
         for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
              Dir != DirEnd && !EC; Dir.increment(EC)) {
-          if (llvm::sys::path::extension(Dir->getName()) != ".framework")
+          if (llvm::sys::path::extension(Dir->path()) != ".framework")
             continue;
 
           const DirectoryEntry *FrameworkDir =
-              FileMgr.getDirectory(Dir->getName());
+              FileMgr.getDirectory(Dir->path());
           if (!FrameworkDir)
             continue;
 
           // Load this framework module.
-          loadFrameworkModule(llvm::sys::path::stem(Dir->getName()),
-                              FrameworkDir, IsSystem);
+          loadFrameworkModule(llvm::sys::path::stem(Dir->path()), FrameworkDir,
+                              IsSystem);
         }
         continue;
       }
@@ -1642,10 +1642,9 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
   vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
   for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
        Dir != DirEnd && !EC; Dir.increment(EC)) {
-    bool IsFramework =
-        llvm::sys::path::extension(Dir->getName()) == ".framework";
+    bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";
     if (IsFramework == SearchDir.isFramework())
-      loadModuleMapFile(Dir->getName(), SearchDir.isSystemHeaderDirectory(),
+      loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(),
                         SearchDir.isFramework());
   }
 
index 87749f7..a1e9138 100644 (file)
@@ -1001,11 +1001,11 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
   for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC),
                                DirEnd;
        Dir != DirEnd && !EC; Dir.increment(EC)) {
-    if (!StringRef(Dir->getName()).endswith(".framework"))
+    if (!StringRef(Dir->path()).endswith(".framework"))
       continue;
 
     if (const DirectoryEntry *SubframeworkDir =
-            FileMgr.getDirectory(Dir->getName())) {
+            FileMgr.getDirectory(Dir->path())) {
       // Note: as an egregious but useful hack, we use the real path here and
       // check whether it is actually a subdirectory of the parent directory.
       // This will not be the case if the 'subframework' is actually a symlink
@@ -2374,10 +2374,9 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
     vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem();
     for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
          I != E && !EC; I.increment(EC)) {
-      if (const FileEntry *FE =
-              SourceMgr.getFileManager().getFile(I->getName())) {
+      if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) {
 
-        Module::Header Header = {I->getName(), FE};
+        Module::Header Header = {I->path(), FE};
         Headers.push_back(std::move(Header));
       }
     }
index 6631b13..2ec075f 100644 (file)
@@ -312,12 +312,12 @@ void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) {
 
     // Check whether this entry has an extension typically associated with
     // headers.
-    if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->getName()))
+    if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->path()))
              .Cases(".h", ".H", ".hh", ".hpp", true)
              .Default(false))
       continue;
 
-    if (const FileEntry *Header = getFileManager().getFile(Entry->getName()))
+    if (const FileEntry *Header = getFileManager().getFile(Entry->path()))
       if (!getSourceManager().hasFileInfo(Header)) {
         if (!ModMap.isHeaderInUnavailableModule(Header)) {
           // Find the relative path that would access this header.
index 3d41db7..7f89d75 100644 (file)
@@ -104,7 +104,8 @@ public:
           Path(_Path.str()) {
       for ( ; I != FilesAndDirs.end(); ++I) {
         if (isInPath(I->first)) {
-          CurrentEntry = I->second;
+          CurrentEntry =
+              vfs::directory_entry(I->second.getName(), I->second.getType());
           break;
         }
       }
@@ -113,12 +114,13 @@ public:
       ++I;
       for ( ; I != FilesAndDirs.end(); ++I) {
         if (isInPath(I->first)) {
-          CurrentEntry = I->second;
+          CurrentEntry =
+              vfs::directory_entry(I->second.getName(), I->second.getType());
           break;
         }
       }
       if (I == FilesAndDirs.end())
-        CurrentEntry = vfs::Status();
+        CurrentEntry = vfs::directory_entry();
       return std::error_code();
     }
   };
@@ -398,11 +400,11 @@ TEST(VirtualFileSystemTest, BasicRealFSIteration) {
   ASSERT_FALSE(EC);
   ASSERT_NE(vfs::directory_iterator(), I);
   // Check either a or c, since we can't rely on the iteration order.
-  EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
+  EXPECT_TRUE(I->path().endswith("a") || I->path().endswith("c"));
   I.increment(EC);
   ASSERT_FALSE(EC);
   ASSERT_NE(vfs::directory_iterator(), I);
-  EXPECT_TRUE(I->getName().endswith("a") || I->getName().endswith("c"));
+  EXPECT_TRUE(I->path().endswith("a") || I->path().endswith("c"));
   I.increment(EC);
   EXPECT_EQ(vfs::directory_iterator(), I);
 }
@@ -438,7 +440,7 @@ TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) {
              << "EC message: " << EC2.message() << "\n";
     }
     ASSERT_FALSE(EC);
-    EXPECT_TRUE(I->getName() == _b);
+    EXPECT_TRUE(I->path() == _b);
   }
 }
 #endif
@@ -464,7 +466,7 @@ TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) {
   std::vector<std::string> Contents;
   for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
        I.increment(EC)) {
-    Contents.push_back(I->getName());
+    Contents.push_back(I->path());
   }
 
   // Check contents, which may be in any order
@@ -507,7 +509,7 @@ TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) {
        I != E; I.increment(EC)) {
     auto EC2 = std::make_error_code(std::errc::no_such_file_or_directory);
     if (EC == EC2) {
-      VisitedBrokenSymlinks.push_back(I->getName());
+      VisitedBrokenSymlinks.push_back(I->path());
       continue;
     }
     // For bot debugging.
@@ -523,7 +525,7 @@ TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) {
              << "EC message: " << EC2.message() << "\n";
     }
     ASSERT_FALSE(EC);
-    VisitedNonBrokenSymlinks.push_back(I->getName());
+    VisitedNonBrokenSymlinks.push_back(I->path());
   }
 
   // Check visited file names.
@@ -549,7 +551,7 @@ static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) {
   // Do not rely on iteration order to check for contents, sort both
   // content vectors before comparison.
   for (DirIter E; !EC && I != E; I.increment(EC))
-    InputToCheck.push_back(I->getName());
+    InputToCheck.push_back(I->path());
 
   llvm::sort(InputToCheck.begin(), InputToCheck.end());
   llvm::sort(Expected.begin(), Expected.end());
@@ -656,14 +658,14 @@ TEST(VirtualFileSystemTest, HiddenInIteration) {
   O->pushOverlay(Upper);
 
   std::error_code EC;
-  Lower->addRegularFile("/onlyInLow", sys::fs::owner_read);
-  Lower->addRegularFile("/hiddenByMid", sys::fs::owner_read);
-  Lower->addRegularFile("/hiddenByUp", sys::fs::owner_read);
-  Middle->addRegularFile("/onlyInMid", sys::fs::owner_write);
-  Middle->addRegularFile("/hiddenByMid", sys::fs::owner_write);
-  Middle->addRegularFile("/hiddenByUp", sys::fs::owner_write);
-  Upper->addRegularFile("/onlyInUp", sys::fs::owner_all);
-  Upper->addRegularFile("/hiddenByUp", sys::fs::owner_all);
+  Lower->addRegularFile("/onlyInLow");
+  Lower->addDirectory("/hiddenByMid");
+  Lower->addDirectory("/hiddenByUp");
+  Middle->addRegularFile("/onlyInMid");
+  Middle->addRegularFile("/hiddenByMid");
+  Middle->addDirectory("/hiddenByUp");
+  Upper->addRegularFile("/onlyInUp");
+  Upper->addRegularFile("/hiddenByUp");
   checkContents(
       O->dir_begin("/", EC),
       {"/hiddenByUp", "/onlyInUp", "/hiddenByMid", "/onlyInMid", "/onlyInLow"});
@@ -673,19 +675,19 @@ TEST(VirtualFileSystemTest, HiddenInIteration) {
     std::error_code EC;
     vfs::directory_iterator I = O->dir_begin("/", EC), E;
     for ( ; !EC && I != E; I.increment(EC))
-      if (I->getName() == "/hiddenByUp")
+      if (I->path() == "/hiddenByUp")
         break;
     ASSERT_NE(E, I);
-    EXPECT_EQ(sys::fs::owner_all, I->getPermissions());
+    EXPECT_EQ(sys::fs::file_type::regular_file, I->type());
   }
   {
     std::error_code EC;
     vfs::directory_iterator I = O->dir_begin("/", EC), E;
     for ( ; !EC && I != E; I.increment(EC))
-      if (I->getName() == "/hiddenByMid")
+      if (I->path() == "/hiddenByMid")
         break;
     ASSERT_NE(E, I);
-    EXPECT_EQ(sys::fs::owner_write, I->getPermissions());
+    EXPECT_EQ(sys::fs::file_type::regular_file, I->type());
   }
 }
 
@@ -792,10 +794,10 @@ TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
   std::error_code EC;
   vfs::directory_iterator I = FS.dir_begin("/", EC);
   ASSERT_FALSE(EC);
-  ASSERT_EQ("/a", I->getName());
+  ASSERT_EQ("/a", I->path());
   I.increment(EC);
   ASSERT_FALSE(EC);
-  ASSERT_EQ("/b", I->getName());
+  ASSERT_EQ("/b", I->path());
   I.increment(EC);
   ASSERT_FALSE(EC);
   ASSERT_EQ(vfs::directory_iterator(), I);
@@ -804,7 +806,7 @@ TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
   ASSERT_FALSE(EC);
   // When on Windows, we end up with "/b\\c" as the name.  Convert to Posix
   // path for the sake of the comparison.
-  ASSERT_EQ("/b/c", getPosixPath(I->getName()));
+  ASSERT_EQ("/b/c", getPosixPath(I->path()));
   I.increment(EC);
   ASSERT_FALSE(EC);
   ASSERT_EQ(vfs::directory_iterator(), I);
@@ -967,7 +969,7 @@ TEST_F(InMemoryFileSystemTest, StatusName) {
   clang::vfs::directory_iterator It = NormalizedFS.dir_begin("../b", EC);
   // When on Windows, we end up with "../b\\c" as the name.  Convert to Posix
   // path for the sake of the comparison.
-  ASSERT_EQ("../b/c", getPosixPath(It->getName()));
+  ASSERT_EQ("../b/c", getPosixPath(It->path()));
 }
 
 TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) {
@@ -1067,7 +1069,7 @@ TEST_F(InMemoryFileSystemTest, RecursiveIterationWithHardLink) {
   std::vector<std::string> Nodes;
   for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
        I.increment(EC)) {
-    Nodes.push_back(getPosixPath(I->getName()));
+    Nodes.push_back(getPosixPath(I->path()));
   }
   EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/a", "/a/b", "/c", "/c/d"));
 }