]> granicus.if.org Git - clang/commitdiff
[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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342232 91177308-0d34-0410-b5e6-96231b3b80d8

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

index c808e9026b8be4cc1e90c89a002ec25202143837..fe660cc0177bb9130a2d37a66db01ec149a8a927 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 9972ac4cba96120ce8e04d2ce93855ac7a7b5d7d..e5eb5e47fdfd4261d300578022ded8b6c88ded8d 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 c302d647b973fa1f0eda22c8ec72f03a7bdd0ebe..adce10854bb2cb293511e180be976c5e7070ec72 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 89119308490ea6cc820252163e9405c9b021a596..fda02b50a2746862e56112e30242329051359af9 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 f1a8720045e71e5ad068409140f7534c9e5cea99..38a09a0dac3f208809bcafd25b6aaf6bc17b56b4 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 74550c410396c6321878c2d05908774a1f83cd52..ddb522ae05ff5fbf3d8e149880ecde86976a9d54 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 2ab020f36ccdb49a288ba3915573a7c76e4478b6..99b9cce7f45bf59a3f51e10d439bb892a2564ced 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 87749f74734c9229609baeae7b97230d5d83714e..a1e91382175b2decf6b90d4da04b6d6f16d83786 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 6631b13b15836f346f13fdb0d136ff02fd4d4897..2ec075fa348bcfb5a97e5f709ffbeffb1d10db2a 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 3d41db7a05d8d85ea741b88c5908042a32a7cb72..7f89d751c7f798342c8a2194796e1e87d52e9344 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"));
 }