diff options
author | Simon Marchi <simon.marchi@ericsson.com> | 2018-08-06 21:48:20 +0000 |
---|---|---|
committer | Simon Marchi <simon.marchi@ericsson.com> | 2018-08-06 21:48:20 +0000 |
commit | ddbabc6b7c3fc401d7b59f4c905c5964cb3c5643 (patch) | |
tree | 36e637942ed2dfdd485a9c35271eaf22aaf56df4 /clang/lib/Basic/VirtualFileSystem.cpp | |
parent | 94b29601ef74d170a4b655839bfdba7c7183e708 (diff) | |
download | llvm-ddbabc6b7c3fc401d7b59f4c905c5964cb3c5643.zip llvm-ddbabc6b7c3fc401d7b59f4c905c5964cb3c5643.tar.gz llvm-ddbabc6b7c3fc401d7b59f4c905c5964cb3c5643.tar.bz2 |
[VirtualFileSystem] InMemoryFileSystem::status: Return a Status with the requested name
Summary:
InMemoryFileSystem::status behaves differently than
RealFileSystem::status. The Name contained in the Status returned by
RealFileSystem::status will be the path as requested by the caller,
whereas InMemoryFileSystem::status returns the normalized path.
For example, when requested the status for "../src/first.h",
RealFileSystem returns a Status with "../src/first.h" as the Name.
InMemoryFileSystem returns "/absolute/path/to/src/first.h".
The reason for this change is that I want to make a unit test in the
clangd testsuite (where we use an InMemoryFileSystem) to reproduce a
bug I get with the clangd program (where a RealFileSystem is used).
This difference in behavior "hides" the bug in the unit test version.
An indirect impact of this change is that a -Wnonportable-include-path
warning is now emitted in test PCH/case-insensitive-include.c. This is
because the real path of the included file (with the wrong case) was not
available previously, whereas it is now.
Reviewers: malaperle, ilya-biryukov, bkramer
Reviewed By: ilya-biryukov
Subscribers: eric_niebler, malaperle, omtcyfz, hokein, bkramer, ilya-biryukov, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D48903
llvm-svn: 339063
Diffstat (limited to 'clang/lib/Basic/VirtualFileSystem.cpp')
-rw-r--r-- | clang/lib/Basic/VirtualFileSystem.cpp | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/clang/lib/Basic/VirtualFileSystem.cpp b/clang/lib/Basic/VirtualFileSystem.cpp index bcfcbdb..a7b8b02 100644 --- a/clang/lib/Basic/VirtualFileSystem.cpp +++ b/clang/lib/Basic/VirtualFileSystem.cpp @@ -474,12 +474,28 @@ class InMemoryNode { Status Stat; InMemoryNodeKind Kind; +protected: + /// Return Stat. This should only be used for internal/debugging use. When + /// clients wants the Status of this node, they should use + /// \p getStatus(StringRef). + const Status &getStatus() const { return Stat; } + public: InMemoryNode(Status Stat, InMemoryNodeKind Kind) : Stat(std::move(Stat)), Kind(Kind) {} virtual ~InMemoryNode() = default; - const Status &getStatus() const { return Stat; } + /// Return the \p Status for this node. \p RequestedName should be the name + /// through which the caller referred to this node. It will override + /// \p Status::Name in the return value, to mimic the behavior of \p RealFile. + Status getStatus(StringRef RequestedName) const { + return Status::copyWithNewName(Stat, RequestedName); + } + + /// Get the filename of this node (the name without the directory part). + StringRef getFileName() const { + return llvm::sys::path::filename(Stat.getName()); + } InMemoryNodeKind getKind() const { return Kind; } virtual std::string toString(unsigned Indent) const = 0; }; @@ -504,14 +520,21 @@ public: } }; -/// Adapt a InMemoryFile for VFS' File interface. +/// Adapt a InMemoryFile for VFS' File interface. The goal is to make +/// \p InMemoryFileAdaptor mimic as much as possible the behavior of +/// \p RealFile. class InMemoryFileAdaptor : public File { InMemoryFile &Node; + /// The name to use when returning a Status for this file. + std::string RequestedName; public: - explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {} + explicit InMemoryFileAdaptor(InMemoryFile &Node, std::string RequestedName) + : Node(Node), RequestedName(std::move(RequestedName)) {} - llvm::ErrorOr<Status> status() override { return Node.getStatus(); } + llvm::ErrorOr<Status> status() override { + return Node.getStatus(RequestedName); + } llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator, @@ -711,7 +734,7 @@ lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir, llvm::ErrorOr<Status> InMemoryFileSystem::status(const Twine &Path) { auto Node = lookupInMemoryNode(*this, Root.get(), Path); if (Node) - return (*Node)->getStatus(); + return (*Node)->getStatus(Path.str()); return Node.getError(); } @@ -724,7 +747,8 @@ InMemoryFileSystem::openFileForRead(const Twine &Path) { // When we have a file provide a heap-allocated wrapper for the memory buffer // to match the ownership semantics for File. if (auto *F = dyn_cast<detail::InMemoryFile>(*Node)) - return std::unique_ptr<File>(new detail::InMemoryFileAdaptor(*F)); + return std::unique_ptr<File>( + new detail::InMemoryFileAdaptor(*F, Path.str())); // FIXME: errc::not_a_file? return make_error_code(llvm::errc::invalid_argument); @@ -736,21 +760,33 @@ namespace { class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl { detail::InMemoryDirectory::const_iterator I; detail::InMemoryDirectory::const_iterator E; + std::string RequestedDirName; + + void setCurrentEntry() { + if (I != E) { + SmallString<256> Path(RequestedDirName); + llvm::sys::path::append(Path, I->second->getFileName()); + CurrentEntry = I->second->getStatus(Path); + } else { + // When we're at the end, make CurrentEntry invalid and DirIterImpl will + // do the rest. + CurrentEntry = Status(); + } + } public: InMemoryDirIterator() = default; - explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir) - : I(Dir.begin()), E(Dir.end()) { - if (I != E) - CurrentEntry = I->second->getStatus(); + explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir, + std::string RequestedDirName) + : I(Dir.begin()), E(Dir.end()), + RequestedDirName(std::move(RequestedDirName)) { + setCurrentEntry(); } std::error_code increment() override { ++I; - // When we're at the end, make CurrentEntry invalid and DirIterImpl will do - // the rest. - CurrentEntry = I != E ? I->second->getStatus() : Status(); + setCurrentEntry(); return {}; } }; @@ -766,7 +802,8 @@ directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir, } if (auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node)) - return directory_iterator(std::make_shared<InMemoryDirIterator>(*DirNode)); + return directory_iterator( + std::make_shared<InMemoryDirIterator>(*DirNode, Dir.str())); EC = make_error_code(llvm::errc::not_a_directory); return directory_iterator(std::make_shared<InMemoryDirIterator>()); |