Skip to content

Commit ea08bee

Browse files
[IncludeTreeFileSystem] Make dir_begin() work as expected in OverlayFileSystem
Make `dir_begin()` in IncludeTreeFileSystem to return no_such_file_or_directory instead of operation_not_permitted. This allows OverlayFileSystem to correctly ignore IncludeTreeFileSystem layer and continue to search the layer below. rdar://127370903 (cherry picked from commit 43f4996)
1 parent 8a82d83 commit ea08bee

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

clang/include/clang/CAS/IncludeTree.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,11 @@ class IncludeTreeRoot : public IncludeTreeBase<IncludeTreeRoot> {
869869
Expected<IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
870870
createIncludeTreeFileSystem(IncludeTreeRoot &Root);
871871

872+
/// Create the same IncludeTreeFileSystem but from IncludeTree::FileList.
873+
Expected<IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
874+
createIncludeTreeFileSystem(llvm::cas::ObjectStore &CAS,
875+
IncludeTree::FileList &List);
876+
872877
} // namespace cas
873878
} // namespace clang
874879

clang/lib/CAS/IncludeTree.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "clang/CAS/IncludeTree.h"
1010
#include "llvm/ADT/ArrayRef.h"
1111
#include "llvm/ADT/SmallBitVector.h"
12+
#include "llvm/CAS/ObjectStore.h"
1213
#include "llvm/Support/EndianStream.h"
1314
#include "llvm/Support/Error.h"
1415
#include <utility>
@@ -1000,7 +1001,9 @@ class IncludeTreeFileSystem : public llvm::vfs::FileSystem {
10001001

10011002
llvm::vfs::directory_iterator dir_begin(const Twine &Dir,
10021003
std::error_code &EC) override {
1003-
EC = llvm::errc::operation_not_permitted;
1004+
// Return no_such_file_or_directory so llvm::vfs::OverlayFileSystem can
1005+
// ignore this layer when iterating directories.
1006+
EC = llvm::errc::no_such_file_or_directory;
10041007
return llvm::vfs::directory_iterator();
10051008
}
10061009
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
@@ -1033,12 +1036,18 @@ cas::createIncludeTreeFileSystem(IncludeTreeRoot &Root) {
10331036
if (!FileList)
10341037
return FileList.takeError();
10351038

1039+
return createIncludeTreeFileSystem(Root.getCAS(), *FileList);
1040+
}
1041+
1042+
Expected<IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
1043+
cas::createIncludeTreeFileSystem(llvm::cas::ObjectStore &CAS,
1044+
IncludeTree::FileList &FileList) {
10361045
// Map from FilenameRef to ContentsRef.
10371046
llvm::DenseMap<ObjectRef, ObjectRef> SeenContents;
10381047

10391048
IntrusiveRefCntPtr<IncludeTreeFileSystem> IncludeTreeFS =
1040-
new IncludeTreeFileSystem(Root.getCAS());
1041-
llvm::Error E = FileList->forEachFile(
1049+
new IncludeTreeFileSystem(CAS);
1050+
llvm::Error E = FileList.forEachFile(
10421051
[&](IncludeTree::File File,
10431052
IncludeTree::FileList::FileSizeTy Size) -> llvm::Error {
10441053
auto InsertPair = SeenContents.insert(

clang/unittests/CAS/IncludeTreeTest.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
#include "llvm/CAS/CachingOnDiskFileSystem.h"
66
#include "llvm/CAS/ObjectStore.h"
77
#include "llvm/Support/Error.h"
8+
#include "llvm/Support/VirtualFileSystem.h"
89
#include "llvm/Testing/Support/Error.h"
910
#include "gtest/gtest.h"
11+
#include <system_error>
1012

1113
using namespace clang;
1214
using namespace clang::cas;
@@ -294,3 +296,48 @@ TEST(IncludeTree, IncludeTreeFileListDuplicates) {
294296
llvm::Succeeded());
295297
EXPECT_EQ(I, Files.size());
296298
}
299+
300+
TEST(IncludeTree, IncludeTreeFileSystemOverlay) {
301+
std::shared_ptr<ObjectStore> DB = llvm::cas::createInMemoryCAS();
302+
SmallVector<IncludeTree::FileList::FileEntry> Files;
303+
for (unsigned I = 0; I < 10; ++I) {
304+
std::optional<IncludeTree::File> File;
305+
std::string Path = "/file" + std::to_string(I);
306+
static constexpr StringRef Bytes = "123456789";
307+
std::optional<ObjectRef> Content;
308+
ASSERT_THAT_ERROR(
309+
DB->storeFromString({}, Bytes.substr(0, I)).moveInto(Content),
310+
llvm::Succeeded());
311+
ASSERT_THAT_ERROR(
312+
IncludeTree::File::create(*DB, Path, *Content).moveInto(File),
313+
llvm::Succeeded());
314+
Files.push_back({File->getRef(), I});
315+
}
316+
std::optional<IncludeTree::FileList> FileList;
317+
ASSERT_THAT_ERROR(
318+
IncludeTree::FileList::create(*DB, Files, {}).moveInto(FileList),
319+
llvm::Succeeded());
320+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> IncludeTreeFS;
321+
ASSERT_THAT_ERROR(
322+
createIncludeTreeFileSystem(*DB, *FileList).moveInto(IncludeTreeFS),
323+
llvm::Succeeded());
324+
325+
auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
326+
FS->setCurrentWorkingDirectory("/dir");
327+
FS->addFile("file1", 0, llvm::MemoryBuffer::getMemBuffer("str"));
328+
FS->addFile("file2", 0, llvm::MemoryBuffer::getMemBuffer("other"));
329+
330+
llvm::vfs::OverlayFileSystem OverlayFS(std::move(FS));
331+
OverlayFS.pushOverlay(IncludeTreeFS);
332+
333+
std::error_code EC;
334+
int NumFile = 0;
335+
for (auto I = OverlayFS.dir_begin("/dir", EC);
336+
!EC && I != llvm::vfs::directory_iterator(); I.increment(EC)) {
337+
ASSERT_FALSE(EC);
338+
++NumFile;
339+
std::string Path = "/dir/file" + std::to_string(NumFile);
340+
ASSERT_EQ(I->path(), Path);
341+
}
342+
ASSERT_EQ(NumFile, 2);
343+
}

0 commit comments

Comments
 (0)