This revision was automatically updated to reflect the committed changes.
Closed by commit rL297510: [VFS] Ignore broken symlinks in the directory 
iterator. (authored by ributzka).

Changed prior to commit:
  https://reviews.llvm.org/D30768?vs=91371&id=91403#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D30768

Files:
  cfe/trunk/include/clang/Basic/VirtualFileSystem.h
  cfe/trunk/lib/Basic/VirtualFileSystem.cpp
  cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp

Index: cfe/trunk/include/clang/Basic/VirtualFileSystem.h
===================================================================
--- cfe/trunk/include/clang/Basic/VirtualFileSystem.h
+++ cfe/trunk/include/clang/Basic/VirtualFileSystem.h
@@ -161,7 +161,7 @@
   directory_iterator &increment(std::error_code &EC) {
     assert(Impl && "attempting to increment past end");
     EC = Impl->increment();
-    if (EC || !Impl->CurrentEntry.isStatusKnown())
+    if (!Impl->CurrentEntry.isStatusKnown())
       Impl.reset(); // Normalize the end iterator to Impl == nullptr.
     return *this;
   }
Index: cfe/trunk/lib/Basic/VirtualFileSystem.cpp
===================================================================
--- cfe/trunk/lib/Basic/VirtualFileSystem.cpp
+++ cfe/trunk/lib/Basic/VirtualFileSystem.cpp
@@ -246,8 +246,7 @@
     if (!EC && Iter != llvm::sys::fs::directory_iterator()) {
       llvm::sys::fs::file_status S;
       EC = Iter->status(S);
-      if (!EC)
-        CurrentEntry = Status::copyWithNewName(S, Iter->path());
+      CurrentEntry = Status::copyWithNewName(S, Iter->path());
     }
   }
 
@@ -1858,7 +1857,7 @@
                                                            std::error_code &EC)
     : FS(&FS_) {
   directory_iterator I = FS->dir_begin(Path, EC);
-  if (!EC && I != directory_iterator()) {
+  if (I != directory_iterator()) {
     State = std::make_shared<IterState>();
     State->push(I);
   }
@@ -1871,8 +1870,6 @@
   vfs::directory_iterator End;
   if (State->top()->isDirectory()) {
     vfs::directory_iterator I = FS->dir_begin(State->top()->getName(), EC);
-    if (EC)
-      return *this;
     if (I != End) {
       State->push(I);
       return *this;
Index: cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp
===================================================================
--- cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp
+++ cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp
@@ -305,6 +305,22 @@
   }
   operator StringRef() { return Path.str(); }
 };
+
+struct ScopedLink {
+  SmallString<128> Path;
+  ScopedLink(const Twine &To, const Twine &From) {
+    Path = From.str();
+    std::error_code EC = sys::fs::create_link(To, From);
+    if (EC)
+      Path = "";
+    EXPECT_FALSE(EC);
+  }
+  ~ScopedLink() {
+    if (Path != "")
+      EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
+  }
+  operator StringRef() { return Path.str(); }
+};
 } // end anonymous namespace
 
 TEST(VirtualFileSystemTest, BasicRealFSIteration) {
@@ -334,6 +350,35 @@
   EXPECT_EQ(vfs::directory_iterator(), I);
 }
 
+TEST(VirtualFileSystemTest, BrokenSymlinkRealFSIteration) {
+  ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
+
+  ScopedLink _a("no_such_file", TestDirectory + "/a");
+  ScopedDir _b(TestDirectory + "/b");
+  ScopedLink _c("no_such_file", TestDirectory + "/c");
+
+  std::error_code EC;
+  vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC);
+  EXPECT_TRUE(EC);
+  EXPECT_NE(vfs::directory_iterator(), I);
+  EC = std::error_code();
+  EXPECT_TRUE(I->getName() == _a);
+  I.increment(EC);
+  EXPECT_FALSE(EC);
+  EXPECT_NE(vfs::directory_iterator(), I);
+  EXPECT_TRUE(I->getName() == _b);
+  I.increment(EC);
+  EXPECT_TRUE(EC);
+  EXPECT_NE(vfs::directory_iterator(), I);
+  EC = std::error_code();
+  EXPECT_NE(vfs::directory_iterator(), I);
+  EXPECT_TRUE(I->getName() == _c);
+  I.increment(EC);
+  EXPECT_FALSE(EC);
+  EXPECT_EQ(vfs::directory_iterator(), I);
+}
+
 TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) {
   ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
   IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
@@ -373,6 +418,44 @@
   EXPECT_EQ(1, Counts[3]); // d
 }
 
+TEST(VirtualFileSystemTest, BrokenSymlinkRealFSRecursiveIteration) {
+  ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
+
+  ScopedLink _a("no_such_file", TestDirectory + "/a");
+  ScopedDir _b(TestDirectory + "/b");
+  ScopedLink _ba("no_such_file", TestDirectory + "/b/a");
+  ScopedDir _bb(TestDirectory + "/b/b");
+  ScopedLink _bc("no_such_file", TestDirectory + "/b/c");
+  ScopedLink _c("no_such_file", TestDirectory + "/c");
+  ScopedDir _d(TestDirectory + "/d");
+  ScopedDir _dd(TestDirectory + "/d/d");
+  ScopedDir _ddd(TestDirectory + "/d/d/d");
+  ScopedLink _e("no_such_file", TestDirectory + "/e");
+
+  std::vector<std::string> Contents;
+  std::error_code EC;
+  for (vfs::recursive_directory_iterator I(*FS, Twine(TestDirectory), EC), E;
+       I != E; I.increment(EC)) {
+    // Skip broken symlinks.
+    if (EC == std::errc::no_such_file_or_directory) {
+      EC = std::error_code();
+      continue;
+    } else if (EC) {
+      break;
+    }
+    Contents.push_back(I->getName());
+  }
+
+  // Check contents.
+  EXPECT_EQ(5U, Contents.size());
+  EXPECT_TRUE(Contents[0] == _b);
+  EXPECT_TRUE(Contents[1] == _bb);
+  EXPECT_TRUE(Contents[2] == _d);
+  EXPECT_TRUE(Contents[3] == _dd);
+  EXPECT_TRUE(Contents[4] == _ddd);
+}
+
 template <typename DirIter>
 static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) {
   std::error_code EC;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to