[llvm-branch-commits] [llvm] 75cd8d7 - Support: Add RedirectingFileSystem::create from simple list of redirections
Duncan P. N. Exon Smith via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Dec 8 17:59:45 PST 2020
Author: Duncan P. N. Exon Smith
Date: 2020-12-08T17:53:30-08:00
New Revision: 75cd8d756d6e88b075fae8fe631fdbb17802bdb8
URL: https://github.com/llvm/llvm-project/commit/75cd8d756d6e88b075fae8fe631fdbb17802bdb8
DIFF: https://github.com/llvm/llvm-project/commit/75cd8d756d6e88b075fae8fe631fdbb17802bdb8.diff
LOG: Support: Add RedirectingFileSystem::create from simple list of redirections
Add an overload of `RedirectingFileSystem::create` that builds a
redirecting filesystem off of a simple vector of string pairs. This is
intended to be used to support `clang::arcmt::FileRemapper` and
`clang::PreprocessorOptions::RemappedFiles`.
Differential Revision: https://reviews.llvm.org/D91317
Added:
Modified:
llvm/include/llvm/Support/VirtualFileSystem.h
llvm/lib/Support/VirtualFileSystem.cpp
llvm/unittests/Support/VirtualFileSystemTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h
index f5290f0c6a98..6547d2cdb629 100644
--- a/llvm/include/llvm/Support/VirtualFileSystem.h
+++ b/llvm/include/llvm/Support/VirtualFileSystem.h
@@ -731,6 +731,11 @@ class RedirectingFileSystem : public vfs::FileSystem {
SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
+ /// Redirect each of the remapped files from first to second.
+ static std::unique_ptr<RedirectingFileSystem>
+ create(ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
+ bool UseExternalNames, FileSystem &ExternalFS);
+
ErrorOr<Status> status(const Twine &Path) override;
ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index de2499295daa..c2ce63964f08 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -1272,7 +1272,8 @@ class llvm::vfs::RedirectingFileSystemParser {
return true;
}
- RedirectingFileSystem::Entry *
+public:
+ static RedirectingFileSystem::Entry *
lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name,
RedirectingFileSystem::Entry *ParentEntry = nullptr) {
if (!ParentEntry) { // Look for a existent root
@@ -1314,6 +1315,7 @@ class llvm::vfs::RedirectingFileSystemParser {
return DE->getLastContent();
}
+private:
void uniqueOverlayTree(RedirectingFileSystem *FS,
RedirectingFileSystem::Entry *SrcE,
RedirectingFileSystem::Entry *NewParentE = nullptr) {
@@ -1682,6 +1684,61 @@ RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
return FS;
}
+std::unique_ptr<RedirectingFileSystem> RedirectingFileSystem::create(
+ ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
+ bool UseExternalNames, FileSystem &ExternalFS) {
+ std::unique_ptr<RedirectingFileSystem> FS(
+ new RedirectingFileSystem(&ExternalFS));
+ FS->UseExternalNames = UseExternalNames;
+
+ StringMap<RedirectingFileSystem::Entry *> Entries;
+
+ for (auto &Mapping : llvm::reverse(RemappedFiles)) {
+ SmallString<128> From = StringRef(Mapping.first);
+ SmallString<128> To = StringRef(Mapping.second);
+ {
+ auto EC = ExternalFS.makeAbsolute(From);
+ (void)EC;
+ assert(!EC && "Could not make absolute path");
+ }
+
+ // Check if we've already mapped this file. The first one we see (in the
+ // reverse iteration) wins.
+ RedirectingFileSystem::Entry *&ToEntry = Entries[From];
+ if (ToEntry)
+ continue;
+
+ // Add parent directories.
+ RedirectingFileSystem::Entry *Parent = nullptr;
+ StringRef FromDirectory = llvm::sys::path::parent_path(From);
+ for (auto I = llvm::sys::path::begin(FromDirectory),
+ E = llvm::sys::path::end(FromDirectory);
+ I != E; ++I) {
+ Parent = RedirectingFileSystemParser::lookupOrCreateEntry(FS.get(), *I,
+ Parent);
+ }
+ assert(Parent && "File without a directory?");
+ {
+ auto EC = ExternalFS.makeAbsolute(To);
+ (void)EC;
+ assert(!EC && "Could not make absolute path");
+ }
+
+ // Add the file.
+ auto NewFile =
+ std::make_unique<RedirectingFileSystem::RedirectingFileEntry>(
+ llvm::sys::path::filename(From), To,
+ UseExternalNames
+ ? RedirectingFileSystem::RedirectingFileEntry::NK_External
+ : RedirectingFileSystem::RedirectingFileEntry::NK_Virtual);
+ ToEntry = NewFile.get();
+ cast<RedirectingFileSystem::RedirectingDirectoryEntry>(Parent)->addContent(
+ std::move(NewFile));
+ }
+
+ return FS;
+}
+
ErrorOr<RedirectingFileSystem::Entry *>
RedirectingFileSystem::lookupPath(const Twine &Path_) const {
SmallString<256> Path;
diff --git a/llvm/unittests/Support/VirtualFileSystemTest.cpp b/llvm/unittests/Support/VirtualFileSystemTest.cpp
index 1b574b36d36b..6aff06b9a72f 100644
--- a/llvm/unittests/Support/VirtualFileSystemTest.cpp
+++ b/llvm/unittests/Support/VirtualFileSystemTest.cpp
@@ -2287,3 +2287,89 @@ TEST_F(VFSFromYAMLTest, YAMLVFSWriterTestHandleDirs) {
EXPECT_FALSE(FS->exists(_b.path("b")));
EXPECT_FALSE(FS->exists(_c.path("c")));
}
+
+TEST(VFSFromRemappedFilesTest, Basic) {
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS =
+ new vfs::InMemoryFileSystem;
+ BaseFS->addFile("//root/b", 0, MemoryBuffer::getMemBuffer("contents of b"));
+ BaseFS->addFile("//root/c", 0, MemoryBuffer::getMemBuffer("contents of c"));
+
+ std::vector<std::pair<std::string, std::string>> RemappedFiles = {
+ {"//root/a/a", "//root/b"},
+ {"//root/a/b/c", "//root/c"},
+ };
+ auto RemappedFS = vfs::RedirectingFileSystem::create(
+ RemappedFiles, /*UseExternalNames=*/false, *BaseFS);
+
+ auto StatA = RemappedFS->status("//root/a/a");
+ auto StatB = RemappedFS->status("//root/a/b/c");
+ ASSERT_TRUE(StatA);
+ ASSERT_TRUE(StatB);
+ EXPECT_EQ("//root/a/a", StatA->getName());
+ EXPECT_EQ("//root/a/b/c", StatB->getName());
+
+ auto BufferA = RemappedFS->getBufferForFile("//root/a/a");
+ auto BufferB = RemappedFS->getBufferForFile("//root/a/b/c");
+ ASSERT_TRUE(BufferA);
+ ASSERT_TRUE(BufferB);
+ EXPECT_EQ("contents of b", (*BufferA)->getBuffer());
+ EXPECT_EQ("contents of c", (*BufferB)->getBuffer());
+}
+
+TEST(VFSFromRemappedFilesTest, UseExternalNames) {
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS =
+ new vfs::InMemoryFileSystem;
+ BaseFS->addFile("//root/b", 0, MemoryBuffer::getMemBuffer("contents of b"));
+ BaseFS->addFile("//root/c", 0, MemoryBuffer::getMemBuffer("contents of c"));
+
+ std::vector<std::pair<std::string, std::string>> RemappedFiles = {
+ {"//root/a/a", "//root/b"},
+ {"//root/a/b/c", "//root/c"},
+ };
+ auto RemappedFS = vfs::RedirectingFileSystem::create(
+ RemappedFiles, /*UseExternalNames=*/true, *BaseFS);
+
+ auto StatA = RemappedFS->status("//root/a/a");
+ auto StatB = RemappedFS->status("//root/a/b/c");
+ ASSERT_TRUE(StatA);
+ ASSERT_TRUE(StatB);
+ EXPECT_EQ("//root/b", StatA->getName());
+ EXPECT_EQ("//root/c", StatB->getName());
+
+ auto BufferA = RemappedFS->getBufferForFile("//root/a/a");
+ auto BufferB = RemappedFS->getBufferForFile("//root/a/b/c");
+ ASSERT_TRUE(BufferA);
+ ASSERT_TRUE(BufferB);
+ EXPECT_EQ("contents of b", (*BufferA)->getBuffer());
+ EXPECT_EQ("contents of c", (*BufferB)->getBuffer());
+}
+
+TEST(VFSFromRemappedFilesTest, LastMappingWins) {
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> BaseFS =
+ new vfs::InMemoryFileSystem;
+ BaseFS->addFile("//root/b", 0, MemoryBuffer::getMemBuffer("contents of b"));
+ BaseFS->addFile("//root/c", 0, MemoryBuffer::getMemBuffer("contents of c"));
+
+ std::vector<std::pair<std::string, std::string>> RemappedFiles = {
+ {"//root/a", "//root/b"},
+ {"//root/a", "//root/c"},
+ };
+ auto RemappedFSKeepName = vfs::RedirectingFileSystem::create(
+ RemappedFiles, /*UseExternalNames=*/false, *BaseFS);
+ auto RemappedFSExternalName = vfs::RedirectingFileSystem::create(
+ RemappedFiles, /*UseExternalNames=*/true, *BaseFS);
+
+ auto StatKeepA = RemappedFSKeepName->status("//root/a");
+ auto StatExternalA = RemappedFSExternalName->status("//root/a");
+ ASSERT_TRUE(StatKeepA);
+ ASSERT_TRUE(StatExternalA);
+ EXPECT_EQ("//root/a", StatKeepA->getName());
+ EXPECT_EQ("//root/c", StatExternalA->getName());
+
+ auto BufferKeepA = RemappedFSKeepName->getBufferForFile("//root/a");
+ auto BufferExternalA = RemappedFSExternalName->getBufferForFile("//root/a");
+ ASSERT_TRUE(BufferKeepA);
+ ASSERT_TRUE(BufferExternalA);
+ EXPECT_EQ("contents of c", (*BufferKeepA)->getBuffer());
+ EXPECT_EQ("contents of c", (*BufferExternalA)->getBuffer());
+}
More information about the llvm-branch-commits
mailing list