[Basic] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC).
llvm-svn: 328735
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//===- VirtualFileSystem.cpp - Virtual File System Layer --------*- C++ -*-===//
|
||||
//===- VirtualFileSystem.cpp - Virtual File System Layer ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@@ -6,30 +6,57 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the VirtualFileSystem interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Basic/VirtualFileSystem.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Chrono.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/YAMLParser.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::vfs;
|
||||
using namespace vfs;
|
||||
using namespace llvm;
|
||||
|
||||
using llvm::sys::fs::file_status;
|
||||
using llvm::sys::fs::file_type;
|
||||
using llvm::sys::fs::perms;
|
||||
@@ -38,13 +65,13 @@ using llvm::sys::fs::UniqueID;
|
||||
Status::Status(const file_status &Status)
|
||||
: UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()),
|
||||
User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
|
||||
Type(Status.type()), Perms(Status.permissions()), IsVFSMapped(false) {}
|
||||
Type(Status.type()), Perms(Status.permissions()) {}
|
||||
|
||||
Status::Status(StringRef Name, UniqueID UID, sys::TimePoint<> MTime,
|
||||
uint32_t User, uint32_t Group, uint64_t Size, file_type Type,
|
||||
perms Perms)
|
||||
: Name(Name), UID(UID), MTime(MTime), User(User), Group(Group), Size(Size),
|
||||
Type(Type), Perms(Perms), IsVFSMapped(false) {}
|
||||
Type(Type), Perms(Perms) {}
|
||||
|
||||
Status Status::copyWithNewName(const Status &In, StringRef NewName) {
|
||||
return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
|
||||
@@ -62,28 +89,34 @@ bool Status::equivalent(const Status &Other) const {
|
||||
assert(isStatusKnown() && Other.isStatusKnown());
|
||||
return getUniqueID() == Other.getUniqueID();
|
||||
}
|
||||
|
||||
bool Status::isDirectory() const {
|
||||
return Type == file_type::directory_file;
|
||||
}
|
||||
|
||||
bool Status::isRegularFile() const {
|
||||
return Type == file_type::regular_file;
|
||||
}
|
||||
|
||||
bool Status::isOther() const {
|
||||
return exists() && !isRegularFile() && !isDirectory() && !isSymlink();
|
||||
}
|
||||
|
||||
bool Status::isSymlink() const {
|
||||
return Type == file_type::symlink_file;
|
||||
}
|
||||
|
||||
bool Status::isStatusKnown() const {
|
||||
return Type != file_type::status_error;
|
||||
}
|
||||
|
||||
bool Status::exists() const {
|
||||
return isStatusKnown() && Type != file_type::file_not_found;
|
||||
}
|
||||
|
||||
File::~File() {}
|
||||
File::~File() = default;
|
||||
|
||||
FileSystem::~FileSystem() {}
|
||||
FileSystem::~FileSystem() = default;
|
||||
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>>
|
||||
FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
|
||||
@@ -97,7 +130,7 @@ FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
|
||||
|
||||
std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
|
||||
if (llvm::sys::path::is_absolute(Path))
|
||||
return std::error_code();
|
||||
return {};
|
||||
|
||||
auto WorkingDir = getCurrentWorkingDirectory();
|
||||
if (!WorkingDir)
|
||||
@@ -118,6 +151,7 @@ static bool isTraversalComponent(StringRef Component) {
|
||||
|
||||
static bool pathHasTraversal(StringRef Path) {
|
||||
using namespace llvm::sys;
|
||||
|
||||
for (StringRef Comp : llvm::make_range(path::begin(Path), path::end(Path)))
|
||||
if (isTraversalComponent(Comp))
|
||||
return true;
|
||||
@@ -130,12 +164,15 @@ static bool pathHasTraversal(StringRef Path) {
|
||||
//===-----------------------------------------------------------------------===/
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief Wrapper around a raw file descriptor.
|
||||
class RealFile : public File {
|
||||
friend class RealFileSystem;
|
||||
|
||||
int FD;
|
||||
Status S;
|
||||
std::string RealName;
|
||||
friend class RealFileSystem;
|
||||
|
||||
RealFile(int FD, StringRef NewName, StringRef NewRealPathName)
|
||||
: FD(FD), S(NewName, {}, {}, {}, {}, {},
|
||||
llvm::sys::fs::file_type::status_error, {}),
|
||||
@@ -145,6 +182,7 @@ class RealFile : public File {
|
||||
|
||||
public:
|
||||
~RealFile() override;
|
||||
|
||||
ErrorOr<Status> status() override;
|
||||
ErrorOr<std::string> getName() override;
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(const Twine &Name,
|
||||
@@ -153,7 +191,9 @@ public:
|
||||
bool IsVolatile) override;
|
||||
std::error_code close() override;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
} // namespace
|
||||
|
||||
RealFile::~RealFile() { close(); }
|
||||
|
||||
ErrorOr<Status> RealFile::status() {
|
||||
@@ -186,6 +226,7 @@ std::error_code RealFile::close() {
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief The file system according to your operating system.
|
||||
class RealFileSystem : public FileSystem {
|
||||
public:
|
||||
@@ -196,7 +237,8 @@ public:
|
||||
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
|
||||
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
} // namespace
|
||||
|
||||
ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
|
||||
sys::fs::file_status RealStatus;
|
||||
@@ -238,8 +280,10 @@ IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class RealFSDirIter : public clang::vfs::detail::DirIterImpl {
|
||||
llvm::sys::fs::directory_iterator Iter;
|
||||
|
||||
public:
|
||||
RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
|
||||
if (!EC && Iter != llvm::sys::fs::directory_iterator()) {
|
||||
@@ -264,7 +308,8 @@ public:
|
||||
return EC;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
|
||||
std::error_code &EC) {
|
||||
@@ -274,6 +319,7 @@ directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
|
||||
//===-----------------------------------------------------------------------===/
|
||||
// OverlayFileSystem implementation
|
||||
//===-----------------------------------------------------------------------===/
|
||||
|
||||
OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) {
|
||||
FSList.push_back(std::move(BaseFS));
|
||||
}
|
||||
@@ -311,17 +357,19 @@ OverlayFileSystem::getCurrentWorkingDirectory() const {
|
||||
// All file systems are synchronized, just take the first working directory.
|
||||
return FSList.front()->getCurrentWorkingDirectory();
|
||||
}
|
||||
|
||||
std::error_code
|
||||
OverlayFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
|
||||
for (auto &FS : FSList)
|
||||
if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
|
||||
return EC;
|
||||
return std::error_code();
|
||||
return {};
|
||||
}
|
||||
|
||||
clang::vfs::detail::DirIterImpl::~DirIterImpl() { }
|
||||
clang::vfs::detail::DirIterImpl::~DirIterImpl() = default;
|
||||
|
||||
namespace {
|
||||
|
||||
class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl {
|
||||
OverlayFileSystem &Overlays;
|
||||
std::string Path;
|
||||
@@ -340,7 +388,7 @@ class OverlayFSDirIterImpl : public clang::vfs::detail::DirIterImpl {
|
||||
if (CurrentDirIter != directory_iterator())
|
||||
break; // found
|
||||
}
|
||||
return std::error_code();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::error_code incrementDirIter(bool IsFirstTime) {
|
||||
@@ -379,7 +427,8 @@ public:
|
||||
|
||||
std::error_code increment() override { return incrementImpl(false); }
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
} // namespace
|
||||
|
||||
directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
|
||||
std::error_code &EC) {
|
||||
@@ -389,6 +438,7 @@ directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
|
||||
|
||||
namespace clang {
|
||||
namespace vfs {
|
||||
|
||||
namespace detail {
|
||||
|
||||
enum InMemoryNodeKind { IME_File, IME_Directory };
|
||||
@@ -402,13 +452,15 @@ class InMemoryNode {
|
||||
public:
|
||||
InMemoryNode(Status Stat, InMemoryNodeKind Kind)
|
||||
: Stat(std::move(Stat)), Kind(Kind) {}
|
||||
virtual ~InMemoryNode() {}
|
||||
virtual ~InMemoryNode() = default;
|
||||
|
||||
const Status &getStatus() const { return Stat; }
|
||||
InMemoryNodeKind getKind() const { return Kind; }
|
||||
virtual std::string toString(unsigned Indent) const = 0;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
class InMemoryFile : public InMemoryNode {
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buffer;
|
||||
|
||||
@@ -417,9 +469,11 @@ public:
|
||||
: InMemoryNode(std::move(Stat), IME_File), Buffer(std::move(Buffer)) {}
|
||||
|
||||
llvm::MemoryBuffer *getBuffer() { return Buffer.get(); }
|
||||
|
||||
std::string toString(unsigned Indent) const override {
|
||||
return (std::string(Indent, ' ') + getStatus().getName() + "\n").str();
|
||||
}
|
||||
|
||||
static bool classof(const InMemoryNode *N) {
|
||||
return N->getKind() == IME_File;
|
||||
}
|
||||
@@ -433,6 +487,7 @@ public:
|
||||
explicit InMemoryFileAdaptor(InMemoryFile &Node) : Node(Node) {}
|
||||
|
||||
llvm::ErrorOr<Status> status() override { return Node.getStatus(); }
|
||||
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
|
||||
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
|
||||
bool IsVolatile) override {
|
||||
@@ -440,9 +495,11 @@ public:
|
||||
return llvm::MemoryBuffer::getMemBuffer(
|
||||
Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
|
||||
}
|
||||
std::error_code close() override { return std::error_code(); }
|
||||
|
||||
std::error_code close() override { return {}; }
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
} // namespace
|
||||
|
||||
class InMemoryDirectory : public InMemoryNode {
|
||||
std::map<std::string, std::unique_ptr<InMemoryNode>> Entries;
|
||||
@@ -450,34 +507,38 @@ class InMemoryDirectory : public InMemoryNode {
|
||||
public:
|
||||
InMemoryDirectory(Status Stat)
|
||||
: InMemoryNode(std::move(Stat), IME_Directory) {}
|
||||
|
||||
InMemoryNode *getChild(StringRef Name) {
|
||||
auto I = Entries.find(Name);
|
||||
if (I != Entries.end())
|
||||
return I->second.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InMemoryNode *addChild(StringRef Name, std::unique_ptr<InMemoryNode> Child) {
|
||||
return Entries.insert(make_pair(Name, std::move(Child)))
|
||||
.first->second.get();
|
||||
}
|
||||
|
||||
typedef decltype(Entries)::const_iterator const_iterator;
|
||||
using const_iterator = decltype(Entries)::const_iterator;
|
||||
|
||||
const_iterator begin() const { return Entries.begin(); }
|
||||
const_iterator end() const { return Entries.end(); }
|
||||
|
||||
std::string toString(unsigned Indent) const override {
|
||||
std::string Result =
|
||||
(std::string(Indent, ' ') + getStatus().getName() + "\n").str();
|
||||
for (const auto &Entry : Entries) {
|
||||
for (const auto &Entry : Entries)
|
||||
Result += Entry.second->toString(Indent + 2);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
static bool classof(const InMemoryNode *N) {
|
||||
return N->getKind() == IME_Directory;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
|
||||
: Root(new detail::InMemoryDirectory(
|
||||
@@ -486,7 +547,7 @@ InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
|
||||
llvm::sys::fs::perms::all_all))),
|
||||
UseNormalizedPaths(UseNormalizedPaths) {}
|
||||
|
||||
InMemoryFileSystem::~InMemoryFileSystem() {}
|
||||
InMemoryFileSystem::~InMemoryFileSystem() = default;
|
||||
|
||||
std::string InMemoryFileSystem::toString() const {
|
||||
return Root->toString(/*Indent=*/0);
|
||||
@@ -645,13 +706,15 @@ InMemoryFileSystem::openFileForRead(const Twine &Path) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// Adaptor from InMemoryDir::iterator to directory_iterator.
|
||||
class InMemoryDirIterator : public clang::vfs::detail::DirIterImpl {
|
||||
detail::InMemoryDirectory::const_iterator I;
|
||||
detail::InMemoryDirectory::const_iterator E;
|
||||
|
||||
public:
|
||||
InMemoryDirIterator() {}
|
||||
InMemoryDirIterator() = default;
|
||||
|
||||
explicit InMemoryDirIterator(detail::InMemoryDirectory &Dir)
|
||||
: I(Dir.begin()), E(Dir.end()) {
|
||||
if (I != E)
|
||||
@@ -663,10 +726,11 @@ public:
|
||||
// When we're at the end, make CurrentEntry invalid and DirIterImpl will do
|
||||
// the rest.
|
||||
CurrentEntry = I != E ? I->second->getStatus() : Status();
|
||||
return std::error_code();
|
||||
return {};
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
} // namespace
|
||||
|
||||
directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
|
||||
std::error_code &EC) {
|
||||
@@ -697,11 +761,12 @@ std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) {
|
||||
|
||||
if (!Path.empty())
|
||||
WorkingDirectory = Path.str();
|
||||
return std::error_code();
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace vfs
|
||||
} // namespace clang
|
||||
|
||||
//===-----------------------------------------------------------------------===/
|
||||
// RedirectingFileSystem implementation
|
||||
//===-----------------------------------------------------------------------===/
|
||||
@@ -719,8 +784,9 @@ class Entry {
|
||||
std::string Name;
|
||||
|
||||
public:
|
||||
virtual ~Entry();
|
||||
Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
|
||||
virtual ~Entry() = default;
|
||||
|
||||
StringRef getName() const { return Name; }
|
||||
EntryKind getKind() const { return Kind; }
|
||||
};
|
||||
@@ -737,14 +803,20 @@ public:
|
||||
S(std::move(S)) {}
|
||||
RedirectingDirectoryEntry(StringRef Name, Status S)
|
||||
: Entry(EK_Directory, Name), S(std::move(S)) {}
|
||||
|
||||
Status getStatus() { return S; }
|
||||
|
||||
void addContent(std::unique_ptr<Entry> Content) {
|
||||
Contents.push_back(std::move(Content));
|
||||
}
|
||||
|
||||
Entry *getLastContent() const { return Contents.back().get(); }
|
||||
typedef decltype(Contents)::iterator iterator;
|
||||
|
||||
using iterator = decltype(Contents)::iterator;
|
||||
|
||||
iterator contents_begin() { return Contents.begin(); }
|
||||
iterator contents_end() { return Contents.end(); }
|
||||
|
||||
static bool classof(const Entry *E) { return E->getKind() == EK_Directory; }
|
||||
};
|
||||
|
||||
@@ -755,21 +827,27 @@ public:
|
||||
NK_External,
|
||||
NK_Virtual
|
||||
};
|
||||
|
||||
private:
|
||||
std::string ExternalContentsPath;
|
||||
NameKind UseName;
|
||||
|
||||
public:
|
||||
RedirectingFileEntry(StringRef Name, StringRef ExternalContentsPath,
|
||||
NameKind UseName)
|
||||
: Entry(EK_File, Name), ExternalContentsPath(ExternalContentsPath),
|
||||
UseName(UseName) {}
|
||||
|
||||
StringRef getExternalContentsPath() const { return ExternalContentsPath; }
|
||||
|
||||
/// \brief whether to use the external path as the name for this file.
|
||||
bool useExternalName(bool GlobalUseExternalName) const {
|
||||
return UseName == NK_NotSet ? GlobalUseExternalName
|
||||
: (UseName == NK_External);
|
||||
}
|
||||
|
||||
NameKind getUseName() const { return UseName; }
|
||||
|
||||
static bool classof(const Entry *E) { return E->getKind() == EK_File; }
|
||||
};
|
||||
|
||||
@@ -785,6 +863,7 @@ public:
|
||||
RedirectingDirectoryEntry::iterator Begin,
|
||||
RedirectingDirectoryEntry::iterator End,
|
||||
std::error_code &EC);
|
||||
|
||||
std::error_code increment() override;
|
||||
};
|
||||
|
||||
@@ -844,10 +923,14 @@ public:
|
||||
/// /path/to/file). However, any directory that contains more than one child
|
||||
/// must be uniquely represented by a directory entry.
|
||||
class RedirectingFileSystem : public vfs::FileSystem {
|
||||
friend class RedirectingFileSystemParser;
|
||||
|
||||
/// The root(s) of the virtual file system.
|
||||
std::vector<std::unique_ptr<Entry>> Roots;
|
||||
|
||||
/// \brief The file system to use for external references.
|
||||
IntrusiveRefCntPtr<FileSystem> ExternalFS;
|
||||
|
||||
/// If IsRelativeOverlay is set, this represents the directory
|
||||
/// path that should be prefixed to each 'external-contents' entry
|
||||
/// when reading from YAML files.
|
||||
@@ -888,8 +971,6 @@ class RedirectingFileSystem : public vfs::FileSystem {
|
||||
true;
|
||||
#endif
|
||||
|
||||
friend class RedirectingFileSystemParser;
|
||||
|
||||
private:
|
||||
RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
|
||||
: ExternalFS(std::move(ExternalFS)) {}
|
||||
@@ -919,6 +1000,7 @@ public:
|
||||
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
|
||||
return ExternalFS->getCurrentWorkingDirectory();
|
||||
}
|
||||
|
||||
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
|
||||
return ExternalFS->setCurrentWorkingDirectory(Path);
|
||||
}
|
||||
@@ -927,17 +1009,17 @@ public:
|
||||
ErrorOr<Entry *> E = lookupPath(Dir);
|
||||
if (!E) {
|
||||
EC = E.getError();
|
||||
return directory_iterator();
|
||||
return {};
|
||||
}
|
||||
ErrorOr<Status> S = status(Dir, *E);
|
||||
if (!S) {
|
||||
EC = S.getError();
|
||||
return directory_iterator();
|
||||
return {};
|
||||
}
|
||||
if (!S->isDirectory()) {
|
||||
EC = std::error_code(static_cast<int>(errc::not_a_directory),
|
||||
std::system_category());
|
||||
return directory_iterator();
|
||||
return {};
|
||||
}
|
||||
|
||||
auto *D = cast<RedirectingDirectoryEntry>(*E);
|
||||
@@ -959,7 +1041,7 @@ public:
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
LLVM_DUMP_METHOD void dump() const {
|
||||
for (const std::unique_ptr<Entry> &Root : Roots)
|
||||
for (const auto &Root : Roots)
|
||||
dumpEntry(Root.get());
|
||||
}
|
||||
|
||||
@@ -979,7 +1061,6 @@ LLVM_DUMP_METHOD void dumpEntry(Entry *E, int NumSpaces = 0) const {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/// \brief A helper class to hold the common YAML parsing state.
|
||||
@@ -993,7 +1074,8 @@ class RedirectingFileSystemParser {
|
||||
// false on error
|
||||
bool parseScalarString(yaml::Node *N, StringRef &Result,
|
||||
SmallVectorImpl<char> &Storage) {
|
||||
yaml::ScalarNode *S = dyn_cast<yaml::ScalarNode>(N);
|
||||
const auto *S = dyn_cast<yaml::ScalarNode>(N);
|
||||
|
||||
if (!S) {
|
||||
error(N, "expected string");
|
||||
return false;
|
||||
@@ -1024,11 +1106,13 @@ class RedirectingFileSystemParser {
|
||||
}
|
||||
|
||||
struct KeyStatus {
|
||||
KeyStatus(bool Required=false) : Required(Required), Seen(false) {}
|
||||
bool Required;
|
||||
bool Seen;
|
||||
bool Seen = false;
|
||||
|
||||
KeyStatus(bool Required = false) : Required(Required) {}
|
||||
};
|
||||
typedef std::pair<StringRef, KeyStatus> KeyStatusPair;
|
||||
|
||||
using KeyStatusPair = std::pair<StringRef, KeyStatus>;
|
||||
|
||||
// false on error
|
||||
bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode, StringRef Key,
|
||||
@@ -1048,11 +1132,9 @@ class RedirectingFileSystemParser {
|
||||
|
||||
// false on error
|
||||
bool checkMissingKeys(yaml::Node *Obj, DenseMap<StringRef, KeyStatus> &Keys) {
|
||||
for (DenseMap<StringRef, KeyStatus>::iterator I = Keys.begin(),
|
||||
E = Keys.end();
|
||||
I != E; ++I) {
|
||||
if (I->second.Required && !I->second.Seen) {
|
||||
error(Obj, Twine("missing key '") + I->first + "'");
|
||||
for (const auto &I : Keys) {
|
||||
if (I.second.Required && !I.second.Seen) {
|
||||
error(Obj, Twine("missing key '") + I.first + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1062,7 +1144,7 @@ class RedirectingFileSystemParser {
|
||||
Entry *lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name,
|
||||
Entry *ParentEntry = nullptr) {
|
||||
if (!ParentEntry) { // Look for a existent root
|
||||
for (const std::unique_ptr<Entry> &Root : FS->Roots) {
|
||||
for (const auto &Root : FS->Roots) {
|
||||
if (Name.equals(Root->getName())) {
|
||||
ParentEntry = Root.get();
|
||||
return ParentEntry;
|
||||
@@ -1125,7 +1207,7 @@ class RedirectingFileSystemParser {
|
||||
}
|
||||
|
||||
std::unique_ptr<Entry> parseEntry(yaml::Node *N, RedirectingFileSystem *FS) {
|
||||
yaml::MappingNode *M = dyn_cast<yaml::MappingNode>(N);
|
||||
auto *M = dyn_cast<yaml::MappingNode>(N);
|
||||
if (!M) {
|
||||
error(N, "expected mapping node for file or directory entry");
|
||||
return nullptr;
|
||||
@@ -1148,21 +1230,20 @@ class RedirectingFileSystemParser {
|
||||
auto UseExternalName = RedirectingFileEntry::NK_NotSet;
|
||||
EntryKind Kind;
|
||||
|
||||
for (yaml::MappingNode::iterator I = M->begin(), E = M->end(); I != E;
|
||||
++I) {
|
||||
for (auto &I : *M) {
|
||||
StringRef Key;
|
||||
// Reuse the buffer for key and value, since we don't look at key after
|
||||
// parsing value.
|
||||
SmallString<256> Buffer;
|
||||
if (!parseScalarString(I->getKey(), Key, Buffer))
|
||||
if (!parseScalarString(I.getKey(), Key, Buffer))
|
||||
return nullptr;
|
||||
|
||||
if (!checkDuplicateOrUnknownKey(I->getKey(), Key, Keys))
|
||||
if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
|
||||
return nullptr;
|
||||
|
||||
StringRef Value;
|
||||
if (Key == "name") {
|
||||
if (!parseScalarString(I->getValue(), Value, Buffer))
|
||||
if (!parseScalarString(I.getValue(), Value, Buffer))
|
||||
return nullptr;
|
||||
|
||||
if (FS->UseCanonicalizedPaths) {
|
||||
@@ -1176,47 +1257,44 @@ class RedirectingFileSystemParser {
|
||||
Name = Value;
|
||||
}
|
||||
} else if (Key == "type") {
|
||||
if (!parseScalarString(I->getValue(), Value, Buffer))
|
||||
if (!parseScalarString(I.getValue(), Value, Buffer))
|
||||
return nullptr;
|
||||
if (Value == "file")
|
||||
Kind = EK_File;
|
||||
else if (Value == "directory")
|
||||
Kind = EK_Directory;
|
||||
else {
|
||||
error(I->getValue(), "unknown value for 'type'");
|
||||
error(I.getValue(), "unknown value for 'type'");
|
||||
return nullptr;
|
||||
}
|
||||
} else if (Key == "contents") {
|
||||
if (HasContents) {
|
||||
error(I->getKey(),
|
||||
error(I.getKey(),
|
||||
"entry already has 'contents' or 'external-contents'");
|
||||
return nullptr;
|
||||
}
|
||||
HasContents = true;
|
||||
yaml::SequenceNode *Contents =
|
||||
dyn_cast<yaml::SequenceNode>(I->getValue());
|
||||
auto *Contents = dyn_cast<yaml::SequenceNode>(I.getValue());
|
||||
if (!Contents) {
|
||||
// FIXME: this is only for directories, what about files?
|
||||
error(I->getValue(), "expected array");
|
||||
error(I.getValue(), "expected array");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (yaml::SequenceNode::iterator I = Contents->begin(),
|
||||
E = Contents->end();
|
||||
I != E; ++I) {
|
||||
if (std::unique_ptr<Entry> E = parseEntry(&*I, FS))
|
||||
for (auto &I : *Contents) {
|
||||
if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
|
||||
EntryArrayContents.push_back(std::move(E));
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
} else if (Key == "external-contents") {
|
||||
if (HasContents) {
|
||||
error(I->getKey(),
|
||||
error(I.getKey(),
|
||||
"entry already has 'contents' or 'external-contents'");
|
||||
return nullptr;
|
||||
}
|
||||
HasContents = true;
|
||||
if (!parseScalarString(I->getValue(), Value, Buffer))
|
||||
if (!parseScalarString(I.getValue(), Value, Buffer))
|
||||
return nullptr;
|
||||
|
||||
SmallString<256> FullPath;
|
||||
@@ -1238,7 +1316,7 @@ class RedirectingFileSystemParser {
|
||||
ExternalContentsPath = FullPath.str();
|
||||
} else if (Key == "use-external-name") {
|
||||
bool Val;
|
||||
if (!parseScalarBool(I->getValue(), Val))
|
||||
if (!parseScalarBool(I.getValue(), Val))
|
||||
return nullptr;
|
||||
UseExternalName = Val ? RedirectingFileEntry::NK_External
|
||||
: RedirectingFileEntry::NK_Virtual;
|
||||
@@ -1311,7 +1389,7 @@ public:
|
||||
|
||||
// false on error
|
||||
bool parse(yaml::Node *Root, RedirectingFileSystem *FS) {
|
||||
yaml::MappingNode *Top = dyn_cast<yaml::MappingNode>(Root);
|
||||
auto *Top = dyn_cast<yaml::MappingNode>(Root);
|
||||
if (!Top) {
|
||||
error(Root, "expected mapping node");
|
||||
return false;
|
||||
@@ -1330,26 +1408,24 @@ public:
|
||||
std::vector<std::unique_ptr<Entry>> RootEntries;
|
||||
|
||||
// Parse configuration and 'roots'
|
||||
for (yaml::MappingNode::iterator I = Top->begin(), E = Top->end(); I != E;
|
||||
++I) {
|
||||
for (auto &I : *Top) {
|
||||
SmallString<10> KeyBuffer;
|
||||
StringRef Key;
|
||||
if (!parseScalarString(I->getKey(), Key, KeyBuffer))
|
||||
if (!parseScalarString(I.getKey(), Key, KeyBuffer))
|
||||
return false;
|
||||
|
||||
if (!checkDuplicateOrUnknownKey(I->getKey(), Key, Keys))
|
||||
if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
|
||||
return false;
|
||||
|
||||
if (Key == "roots") {
|
||||
yaml::SequenceNode *Roots = dyn_cast<yaml::SequenceNode>(I->getValue());
|
||||
auto *Roots = dyn_cast<yaml::SequenceNode>(I.getValue());
|
||||
if (!Roots) {
|
||||
error(I->getValue(), "expected array");
|
||||
error(I.getValue(), "expected array");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (yaml::SequenceNode::iterator I = Roots->begin(), E = Roots->end();
|
||||
I != E; ++I) {
|
||||
if (std::unique_ptr<Entry> E = parseEntry(&*I, FS))
|
||||
for (auto &I : *Roots) {
|
||||
if (std::unique_ptr<Entry> E = parseEntry(&I, FS))
|
||||
RootEntries.push_back(std::move(E));
|
||||
else
|
||||
return false;
|
||||
@@ -1357,32 +1433,32 @@ public:
|
||||
} else if (Key == "version") {
|
||||
StringRef VersionString;
|
||||
SmallString<4> Storage;
|
||||
if (!parseScalarString(I->getValue(), VersionString, Storage))
|
||||
if (!parseScalarString(I.getValue(), VersionString, Storage))
|
||||
return false;
|
||||
int Version;
|
||||
if (VersionString.getAsInteger<int>(10, Version)) {
|
||||
error(I->getValue(), "expected integer");
|
||||
error(I.getValue(), "expected integer");
|
||||
return false;
|
||||
}
|
||||
if (Version < 0) {
|
||||
error(I->getValue(), "invalid version number");
|
||||
error(I.getValue(), "invalid version number");
|
||||
return false;
|
||||
}
|
||||
if (Version != 0) {
|
||||
error(I->getValue(), "version mismatch, expected 0");
|
||||
error(I.getValue(), "version mismatch, expected 0");
|
||||
return false;
|
||||
}
|
||||
} else if (Key == "case-sensitive") {
|
||||
if (!parseScalarBool(I->getValue(), FS->CaseSensitive))
|
||||
if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
|
||||
return false;
|
||||
} else if (Key == "overlay-relative") {
|
||||
if (!parseScalarBool(I->getValue(), FS->IsRelativeOverlay))
|
||||
if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
|
||||
return false;
|
||||
} else if (Key == "use-external-names") {
|
||||
if (!parseScalarBool(I->getValue(), FS->UseExternalNames))
|
||||
if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
|
||||
return false;
|
||||
} else if (Key == "ignore-non-existent-contents") {
|
||||
if (!parseScalarBool(I->getValue(), FS->IgnoreNonExistentContents))
|
||||
if (!parseScalarBool(I.getValue(), FS->IgnoreNonExistentContents))
|
||||
return false;
|
||||
} else {
|
||||
llvm_unreachable("key missing from Keys");
|
||||
@@ -1398,22 +1474,20 @@ public:
|
||||
// Now that we sucessefully parsed the YAML file, canonicalize the internal
|
||||
// representation to a proper directory tree so that we can search faster
|
||||
// inside the VFS.
|
||||
for (std::unique_ptr<Entry> &E : RootEntries)
|
||||
for (auto &E : RootEntries)
|
||||
uniqueOverlayTree(FS, E.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
Entry::~Entry() = default;
|
||||
} // namespace
|
||||
|
||||
RedirectingFileSystem *
|
||||
RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
|
||||
SourceMgr::DiagHandlerTy DiagHandler,
|
||||
StringRef YAMLFilePath, void *DiagContext,
|
||||
IntrusiveRefCntPtr<FileSystem> ExternalFS) {
|
||||
|
||||
SourceMgr SM;
|
||||
yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
|
||||
|
||||
@@ -1473,7 +1547,7 @@ ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) {
|
||||
|
||||
sys::path::const_iterator Start = sys::path::begin(Path);
|
||||
sys::path::const_iterator End = sys::path::end(Path);
|
||||
for (const std::unique_ptr<Entry> &Root : Roots) {
|
||||
for (const auto &Root : Roots) {
|
||||
ErrorOr<Entry *> Result = lookupPath(Start, End, Root.get());
|
||||
if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
|
||||
return Result;
|
||||
@@ -1557,6 +1631,7 @@ ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// Provide a file wrapper with an overriden status.
|
||||
class FileWithFixedStatus : public File {
|
||||
std::unique_ptr<File> InnerFile;
|
||||
@@ -1568,14 +1643,17 @@ public:
|
||||
|
||||
ErrorOr<Status> status() override { return S; }
|
||||
ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
|
||||
|
||||
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
|
||||
bool IsVolatile) override {
|
||||
return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
|
||||
IsVolatile);
|
||||
}
|
||||
|
||||
std::error_code close() override { return InnerFile->close(); }
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
} // namespace
|
||||
|
||||
ErrorOr<std::unique_ptr<File>>
|
||||
RedirectingFileSystem::openFileForRead(const Twine &Path) {
|
||||
@@ -1670,11 +1748,13 @@ void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class JSONWriter {
|
||||
llvm::raw_ostream &OS;
|
||||
SmallVector<StringRef, 16> DirStack;
|
||||
inline unsigned getDirIndent() { return 4 * DirStack.size(); }
|
||||
inline unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
|
||||
|
||||
unsigned getDirIndent() { return 4 * DirStack.size(); }
|
||||
unsigned getFileIndent() { return 4 * (DirStack.size() + 1); }
|
||||
bool containedIn(StringRef Parent, StringRef Path);
|
||||
StringRef containedPart(StringRef Parent, StringRef Path);
|
||||
void startDirectory(StringRef Path);
|
||||
@@ -1683,14 +1763,17 @@ class JSONWriter {
|
||||
|
||||
public:
|
||||
JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
|
||||
|
||||
void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
|
||||
Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
|
||||
Optional<bool> IgnoreNonExistentContents, StringRef OverlayDir);
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool JSONWriter::containedIn(StringRef Parent, StringRef Path) {
|
||||
using namespace llvm::sys;
|
||||
|
||||
// Compare each path component.
|
||||
auto IParent = path::begin(Parent), EParent = path::end(Parent);
|
||||
for (auto IChild = path::begin(Path), EChild = path::end(Path);
|
||||
@@ -1868,7 +1951,7 @@ std::error_code VFSFromYamlDirIterImpl::increment() {
|
||||
|
||||
if (Current == End)
|
||||
CurrentEntry = Status();
|
||||
return std::error_code();
|
||||
return {};
|
||||
}
|
||||
|
||||
vfs::recursive_directory_iterator::recursive_directory_iterator(FileSystem &FS_,
|
||||
|
||||
Reference in New Issue
Block a user