diff --git a/include/llvm/Support/VirtualFileSystem.h b/include/llvm/Support/VirtualFileSystem.h
new file mode 100644
index 0000000..f2f8ffa
--- /dev/null
+++ b/include/llvm/Support/VirtualFileSystem.h
@@ -0,0 +1,522 @@
+//===- VirtualFileSystem.h - Virtual File System Layer ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Defines the virtual file system interface vfs::FileSystem.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_VIRTUALFILESYSTEM_H
+#define LLVM_SUPPORT_VIRTUALFILESYSTEM_H
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/SourceMgr.h"
+#include <cassert>
+#include <cstdint>
+#include <ctime>
+#include <memory>
+#include <stack>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+class MemoryBuffer;
+
+namespace vfs {
+
+/// The result of a \p status operation.
+class Status {
+  std::string Name;
+  llvm::sys::fs::UniqueID UID;
+  llvm::sys::TimePoint<> MTime;
+  uint32_t User;
+  uint32_t Group;
+  uint64_t Size;
+  llvm::sys::fs::file_type Type = llvm::sys::fs::file_type::status_error;
+  llvm::sys::fs::perms Perms;
+
+public:
+  // FIXME: remove when files support multiple names
+  bool IsVFSMapped = false;
+
+  Status() = default;
+  Status(const llvm::sys::fs::file_status &Status);
+  Status(StringRef Name, llvm::sys::fs::UniqueID UID,
+         llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group,
+         uint64_t Size, llvm::sys::fs::file_type Type,
+         llvm::sys::fs::perms Perms);
+
+  /// Get a copy of a Status with a different name.
+  static Status copyWithNewName(const Status &In, StringRef NewName);
+  static Status copyWithNewName(const llvm::sys::fs::file_status &In,
+                                StringRef NewName);
+
+  /// Returns the name that should be used for this file or directory.
+  StringRef getName() const { return Name; }
+
+  /// @name Status interface from llvm::sys::fs
+  /// @{
+  llvm::sys::fs::file_type getType() const { return Type; }
+  llvm::sys::fs::perms getPermissions() const { return Perms; }
+  llvm::sys::TimePoint<> getLastModificationTime() const { return MTime; }
+  llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
+  uint32_t getUser() const { return User; }
+  uint32_t getGroup() const { return Group; }
+  uint64_t getSize() const { return Size; }
+  /// @}
+  /// @name Status queries
+  /// These are static queries in llvm::sys::fs.
+  /// @{
+  bool equivalent(const Status &Other) const;
+  bool isDirectory() const;
+  bool isRegularFile() const;
+  bool isOther() const;
+  bool isSymlink() const;
+  bool isStatusKnown() const;
+  bool exists() const;
+  /// @}
+};
+
+/// Represents an open file.
+class File {
+public:
+  /// Destroy the file after closing it (if open).
+  /// Sub-classes should generally call close() inside their destructors.  We
+  /// cannot do that from the base class, since close is virtual.
+  virtual ~File();
+
+  /// Get the status of the file.
+  virtual llvm::ErrorOr<Status> status() = 0;
+
+  /// Get the name of the file
+  virtual llvm::ErrorOr<std::string> getName() {
+    if (auto Status = status())
+      return Status->getName().str();
+    else
+      return Status.getError();
+  }
+
+  /// Get the contents of the file as a \p MemoryBuffer.
+  virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+  getBuffer(const Twine &Name, int64_t FileSize = -1,
+            bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
+
+  /// Closes the file.
+  virtual std::error_code close() = 0;
+};
+
+/// A member of a directory, yielded by a directory_iterator.
+/// Only information available on most platforms is included.
+class directory_entry {
+  std::string Path;
+  llvm::sys::fs::file_type Type;
+
+public:
+  directory_entry() = default;
+  directory_entry(std::string Path, llvm::sys::fs::file_type Type)
+      : Path(std::move(Path)), Type(Type) {}
+
+  llvm::StringRef path() const { return Path; }
+  llvm::sys::fs::file_type type() const { return Type; }
+};
+
+namespace detail {
+
+/// An interface for virtual file systems to provide an iterator over the
+/// (non-recursive) contents of a directory.
+struct DirIterImpl {
+  virtual ~DirIterImpl();
+
+  /// Sets \c CurrentEntry to the next entry in the directory on success,
+  /// to directory_entry() at end,  or returns a system-defined \c error_code.
+  virtual std::error_code increment() = 0;
+
+  directory_entry CurrentEntry;
+};
+
+} // namespace detail
+
+/// An input iterator over the entries in a virtual path, similar to
+/// llvm::sys::fs::directory_iterator.
+class directory_iterator {
+  std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy
+
+public:
+  directory_iterator(std::shared_ptr<detail::DirIterImpl> I)
+      : Impl(std::move(I)) {
+    assert(Impl.get() != nullptr && "requires non-null implementation");
+    if (Impl->CurrentEntry.path().empty())
+      Impl.reset(); // Normalize the end iterator to Impl == nullptr.
+  }
+
+  /// Construct an 'end' iterator.
+  directory_iterator() = default;
+
+  /// Equivalent to operator++, with an error code.
+  directory_iterator &increment(std::error_code &EC) {
+    assert(Impl && "attempting to increment past end");
+    EC = Impl->increment();
+    if (Impl->CurrentEntry.path().empty())
+      Impl.reset(); // Normalize the end iterator to Impl == nullptr.
+    return *this;
+  }
+
+  const directory_entry &operator*() const { return Impl->CurrentEntry; }
+  const directory_entry *operator->() const { return &Impl->CurrentEntry; }
+
+  bool operator==(const directory_iterator &RHS) const {
+    if (Impl && RHS.Impl)
+      return Impl->CurrentEntry.path() == RHS.Impl->CurrentEntry.path();
+    return !Impl && !RHS.Impl;
+  }
+  bool operator!=(const directory_iterator &RHS) const {
+    return !(*this == RHS);
+  }
+};
+
+class FileSystem;
+
+/// An input iterator over the recursive contents of a virtual path,
+/// similar to llvm::sys::fs::recursive_directory_iterator.
+class recursive_directory_iterator {
+  using IterState =
+      std::stack<directory_iterator, std::vector<directory_iterator>>;
+
+  FileSystem *FS;
+  std::shared_ptr<IterState> State; // Input iterator semantics on copy.
+
+public:
+  recursive_directory_iterator(FileSystem &FS, const Twine &Path,
+                               std::error_code &EC);
+
+  /// Construct an 'end' iterator.
+  recursive_directory_iterator() = default;
+
+  /// Equivalent to operator++, with an error code.
+  recursive_directory_iterator &increment(std::error_code &EC);
+
+  const directory_entry &operator*() const { return *State->top(); }
+  const directory_entry *operator->() const { return &*State->top(); }
+
+  bool operator==(const recursive_directory_iterator &Other) const {
+    return State == Other.State; // identity
+  }
+  bool operator!=(const recursive_directory_iterator &RHS) const {
+    return !(*this == RHS);
+  }
+
+  /// Gets the current level. Starting path is at level 0.
+  int level() const {
+    assert(!State->empty() && "Cannot get level without any iteration state");
+    return State->size() - 1;
+  }
+};
+
+/// The virtual file system interface.
+class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem> {
+public:
+  virtual ~FileSystem();
+
+  /// Get the status of the entry at \p Path, if one exists.
+  virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
+
+  /// Get a \p File object for the file at \p Path, if one exists.
+  virtual llvm::ErrorOr<std::unique_ptr<File>>
+  openFileForRead(const Twine &Path) = 0;
+
+  /// This is a convenience method that opens a file, gets its content and then
+  /// closes the file.
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+  getBufferForFile(const Twine &Name, int64_t FileSize = -1,
+                   bool RequiresNullTerminator = true, bool IsVolatile = false);
+
+  /// Get a directory_iterator for \p Dir.
+  /// \note The 'end' iterator is directory_iterator().
+  virtual directory_iterator dir_begin(const Twine &Dir,
+                                       std::error_code &EC) = 0;
+
+  /// Set the working directory. This will affect all following operations on
+  /// this file system and may propagate down for nested file systems.
+  virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
+
+  /// Get the working directory of this file system.
+  virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const = 0;
+
+  /// Gets real path of \p Path e.g. collapse all . and .. patterns, resolve
+  /// symlinks. For real file system, this uses `llvm::sys::fs::real_path`.
+  /// This returns errc::operation_not_permitted if not implemented by subclass.
+  virtual std::error_code getRealPath(const Twine &Path,
+                                      SmallVectorImpl<char> &Output) const;
+
+  /// Check whether a file exists. Provided for convenience.
+  bool exists(const Twine &Path);
+
+  /// Make \a Path an absolute path.
+  ///
+  /// Makes \a Path absolute using the current directory if it is not already.
+  /// An empty \a Path will result in the current directory.
+  ///
+  /// /absolute/path   => /absolute/path
+  /// relative/../path => <current-directory>/relative/../path
+  ///
+  /// \param Path A path that is modified to be an absolute path.
+  /// \returns success if \a path has been made absolute, otherwise a
+  ///          platform-specific error_code.
+  std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
+};
+
+/// Gets an \p vfs::FileSystem for the 'real' file system, as seen by
+/// the operating system.
+IntrusiveRefCntPtr<FileSystem> getRealFileSystem();
+
+/// A file system that allows overlaying one \p AbstractFileSystem on top
+/// of another.
+///
+/// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
+/// one merged file system. When there is a directory that exists in more than
+/// one file system, the \p OverlayFileSystem contains a directory containing
+/// the union of their contents.  The attributes (permissions, etc.) of the
+/// top-most (most recently added) directory are used.  When there is a file
+/// that exists in more than one file system, the file in the top-most file
+/// system overrides the other(s).
+class OverlayFileSystem : public FileSystem {
+  using FileSystemList = SmallVector<IntrusiveRefCntPtr<FileSystem>, 1>;
+
+  /// The stack of file systems, implemented as a list in order of
+  /// their addition.
+  FileSystemList FSList;
+
+public:
+  OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> Base);
+
+  /// Pushes a file system on top of the stack.
+  void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS);
+
+  llvm::ErrorOr<Status> status(const Twine &Path) override;
+  llvm::ErrorOr<std::unique_ptr<File>>
+  openFileForRead(const Twine &Path) override;
+  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
+  std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
+  std::error_code getRealPath(const Twine &Path,
+                              SmallVectorImpl<char> &Output) const override;
+
+  using iterator = FileSystemList::reverse_iterator;
+  using const_iterator = FileSystemList::const_reverse_iterator;
+
+  /// Get an iterator pointing to the most recently added file system.
+  iterator overlays_begin() { return FSList.rbegin(); }
+  const_iterator overlays_begin() const { return FSList.rbegin(); }
+
+  /// Get an iterator pointing one-past the least recently added file
+  /// system.
+  iterator overlays_end() { return FSList.rend(); }
+  const_iterator overlays_end() const { return FSList.rend(); }
+};
+
+/// By default, this delegates all calls to the underlying file system. This
+/// is useful when derived file systems want to override some calls and still
+/// proxy other calls.
+class ProxyFileSystem : public FileSystem {
+public:
+  explicit ProxyFileSystem(IntrusiveRefCntPtr<FileSystem> FS)
+      : FS(std::move(FS)) {}
+
+  llvm::ErrorOr<Status> status(const Twine &Path) override {
+    return FS->status(Path);
+  }
+  llvm::ErrorOr<std::unique_ptr<File>>
+  openFileForRead(const Twine &Path) override {
+    return FS->openFileForRead(Path);
+  }
+  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
+    return FS->dir_begin(Dir, EC);
+  }
+  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+    return FS->getCurrentWorkingDirectory();
+  }
+  std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
+    return FS->setCurrentWorkingDirectory(Path);
+  }
+  std::error_code getRealPath(const Twine &Path,
+                              SmallVectorImpl<char> &Output) const override {
+    return FS->getRealPath(Path, Output);
+  }
+
+protected:
+  FileSystem &getUnderlyingFS() { return *FS; }
+
+private:
+  IntrusiveRefCntPtr<FileSystem> FS;
+};
+
+namespace detail {
+
+class InMemoryDirectory;
+class InMemoryFile;
+
+} // namespace detail
+
+/// An in-memory file system.
+class InMemoryFileSystem : public FileSystem {
+  std::unique_ptr<detail::InMemoryDirectory> Root;
+  std::string WorkingDirectory;
+  bool UseNormalizedPaths = true;
+
+  /// If HardLinkTarget is non-null, a hardlink is created to the To path which
+  /// must be a file. If it is null then it adds the file as the public addFile.
+  bool addFile(const Twine &Path, time_t ModificationTime,
+               std::unique_ptr<llvm::MemoryBuffer> Buffer,
+               Optional<uint32_t> User, Optional<uint32_t> Group,
+               Optional<llvm::sys::fs::file_type> Type,
+               Optional<llvm::sys::fs::perms> Perms,
+               const detail::InMemoryFile *HardLinkTarget);
+
+public:
+  explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
+  ~InMemoryFileSystem() override;
+
+  /// Add a file containing a buffer or a directory to the VFS with a
+  /// path. The VFS owns the buffer.  If present, User, Group, Type
+  /// and Perms apply to the newly-created file or directory.
+  /// \return true if the file or directory was successfully added,
+  /// false if the file or directory already exists in the file system with
+  /// different contents.
+  bool addFile(const Twine &Path, time_t ModificationTime,
+               std::unique_ptr<llvm::MemoryBuffer> Buffer,
+               Optional<uint32_t> User = None, Optional<uint32_t> Group = None,
+               Optional<llvm::sys::fs::file_type> Type = None,
+               Optional<llvm::sys::fs::perms> Perms = None);
+
+  /// Add a hard link to a file.
+  /// Here hard links are not intended to be fully equivalent to the classical
+  /// filesystem. Both the hard link and the file share the same buffer and
+  /// status (and thus have the same UniqueID). Because of this there is no way
+  /// to distinguish between the link and the file after the link has been
+  /// added.
+  ///
+  /// The To path must be an existing file or a hardlink. The From file must not
+  /// have been added before. The To Path must not be a directory. The From Node
+  /// is added as a hard link which points to the resolved file of To Node.
+  /// \return true if the above condition is satisfied and hardlink was
+  /// successfully created, false otherwise.
+  bool addHardLink(const Twine &From, const Twine &To);
+
+  /// Add a buffer to the VFS with a path. The VFS does not own the buffer.
+  /// If present, User, Group, Type and Perms apply to the newly-created file
+  /// or directory.
+  /// \return true if the file or directory was successfully added,
+  /// false if the file or directory already exists in the file system with
+  /// different contents.
+  bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
+                    llvm::MemoryBuffer *Buffer, Optional<uint32_t> User = None,
+                    Optional<uint32_t> Group = None,
+                    Optional<llvm::sys::fs::file_type> Type = None,
+                    Optional<llvm::sys::fs::perms> Perms = None);
+
+  std::string toString() const;
+
+  /// Return true if this file system normalizes . and .. in paths.
+  bool useNormalizedPaths() const { return UseNormalizedPaths; }
+
+  llvm::ErrorOr<Status> status(const Twine &Path) override;
+  llvm::ErrorOr<std::unique_ptr<File>>
+  openFileForRead(const Twine &Path) override;
+  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+
+  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+    return WorkingDirectory;
+  }
+  /// Canonicalizes \p Path by combining with the current working
+  /// directory and normalizing the path (e.g. remove dots). If the current
+  /// working directory is not set, this returns errc::operation_not_permitted.
+  ///
+  /// This doesn't resolve symlinks as they are not supported in in-memory file
+  /// system.
+  std::error_code getRealPath(const Twine &Path,
+                              SmallVectorImpl<char> &Output) const override;
+
+  std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
+};
+
+/// Get a globally unique ID for a virtual file or directory.
+llvm::sys::fs::UniqueID getNextVirtualUniqueID();
+
+/// Gets a \p FileSystem for a virtual file system described in YAML
+/// format.
+IntrusiveRefCntPtr<FileSystem>
+getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
+               llvm::SourceMgr::DiagHandlerTy DiagHandler,
+               StringRef YAMLFilePath, void *DiagContext = nullptr,
+               IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem());
+
+struct YAMLVFSEntry {
+  template <typename T1, typename T2>
+  YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
+      : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)) {}
+  std::string VPath;
+  std::string RPath;
+};
+
+/// Collect all pairs of <virtual path, real path> entries from the
+/// \p YAMLFilePath. This is used by the module dependency collector to forward
+/// the entries into the reproducer output VFS YAML file.
+void collectVFSFromYAML(
+    std::unique_ptr<llvm::MemoryBuffer> Buffer,
+    llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
+    SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
+    void *DiagContext = nullptr,
+    IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem());
+
+class YAMLVFSWriter {
+  std::vector<YAMLVFSEntry> Mappings;
+  Optional<bool> IsCaseSensitive;
+  Optional<bool> IsOverlayRelative;
+  Optional<bool> UseExternalNames;
+  Optional<bool> IgnoreNonExistentContents;
+  std::string OverlayDir;
+
+public:
+  YAMLVFSWriter() = default;
+
+  void addFileMapping(StringRef VirtualPath, StringRef RealPath);
+
+  void setCaseSensitivity(bool CaseSensitive) {
+    IsCaseSensitive = CaseSensitive;
+  }
+
+  void setUseExternalNames(bool UseExtNames) { UseExternalNames = UseExtNames; }
+
+  void setIgnoreNonExistentContents(bool IgnoreContents) {
+    IgnoreNonExistentContents = IgnoreContents;
+  }
+
+  void setOverlayDir(StringRef OverlayDirectory) {
+    IsOverlayRelative = true;
+    OverlayDir.assign(OverlayDirectory.str());
+  }
+
+  void write(llvm::raw_ostream &OS);
+};
+
+} // namespace vfs
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_VIRTUALFILESYSTEM_H
diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt
index 88129b0..1446359 100644
--- a/lib/Support/CMakeLists.txt
+++ b/lib/Support/CMakeLists.txt
@@ -135,6 +135,7 @@
   Unicode.cpp
   UnicodeCaseFold.cpp
   VersionTuple.cpp
+  VirtualFileSystem.cpp
   WithColor.cpp
   YAMLParser.cpp
   YAMLTraits.cpp
diff --git a/lib/Support/VirtualFileSystem.cpp b/lib/Support/VirtualFileSystem.cpp
new file mode 100644
index 0000000..23b5fbc
--- /dev/null
+++ b/lib/Support/VirtualFileSystem.cpp
@@ -0,0 +1,2121 @@
+//===- VirtualFileSystem.cpp - Virtual File System Layer ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the VirtualFileSystem interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.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/Casting.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/Compiler.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 <mutex>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::vfs;
+
+using llvm::sys::fs::file_status;
+using llvm::sys::fs::file_type;
+using llvm::sys::fs::perms;
+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()) {}
+
+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) {}
+
+Status Status::copyWithNewName(const Status &In, StringRef NewName) {
+  return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
+                In.getUser(), In.getGroup(), In.getSize(), In.getType(),
+                In.getPermissions());
+}
+
+Status Status::copyWithNewName(const file_status &In, StringRef NewName) {
+  return Status(NewName, In.getUniqueID(), In.getLastModificationTime(),
+                In.getUser(), In.getGroup(), In.getSize(), In.type(),
+                In.permissions());
+}
+
+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() = default;
+
+FileSystem::~FileSystem() = default;
+
+ErrorOr<std::unique_ptr<MemoryBuffer>>
+FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize,
+                             bool RequiresNullTerminator, bool IsVolatile) {
+  auto F = openFileForRead(Name);
+  if (!F)
+    return F.getError();
+
+  return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
+}
+
+std::error_code FileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const {
+  if (llvm::sys::path::is_absolute(Path))
+    return {};
+
+  auto WorkingDir = getCurrentWorkingDirectory();
+  if (!WorkingDir)
+    return WorkingDir.getError();
+
+  return llvm::sys::fs::make_absolute(WorkingDir.get(), Path);
+}
+
+std::error_code FileSystem::getRealPath(const Twine &Path,
+                                        SmallVectorImpl<char> &Output) const {
+  return errc::operation_not_permitted;
+}
+
+bool FileSystem::exists(const Twine &Path) {
+  auto Status = status(Path);
+  return Status && Status->exists();
+}
+
+#ifndef NDEBUG
+static bool isTraversalComponent(StringRef Component) {
+  return Component.equals("..") || Component.equals(".");
+}
+
+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;
+  return false;
+}
+#endif
+
+//===-----------------------------------------------------------------------===/
+// RealFileSystem implementation
+//===-----------------------------------------------------------------------===/
+
+namespace {
+
+/// Wrapper around a raw file descriptor.
+class RealFile : public File {
+  friend class RealFileSystem;
+
+  int FD;
+  Status S;
+  std::string RealName;
+
+  RealFile(int FD, StringRef NewName, StringRef NewRealPathName)
+      : FD(FD), S(NewName, {}, {}, {}, {}, {},
+                  llvm::sys::fs::file_type::status_error, {}),
+        RealName(NewRealPathName.str()) {
+    assert(FD >= 0 && "Invalid or inactive file descriptor");
+  }
+
+public:
+  ~RealFile() override;
+
+  ErrorOr<Status> status() override;
+  ErrorOr<std::string> getName() override;
+  ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(const Twine &Name,
+                                                   int64_t FileSize,
+                                                   bool RequiresNullTerminator,
+                                                   bool IsVolatile) override;
+  std::error_code close() override;
+};
+
+} // namespace
+
+RealFile::~RealFile() { close(); }
+
+ErrorOr<Status> RealFile::status() {
+  assert(FD != -1 && "cannot stat closed file");
+  if (!S.isStatusKnown()) {
+    file_status RealStatus;
+    if (std::error_code EC = sys::fs::status(FD, RealStatus))
+      return EC;
+    S = Status::copyWithNewName(RealStatus, S.getName());
+  }
+  return S;
+}
+
+ErrorOr<std::string> RealFile::getName() {
+  return RealName.empty() ? S.getName().str() : RealName;
+}
+
+ErrorOr<std::unique_ptr<MemoryBuffer>>
+RealFile::getBuffer(const Twine &Name, int64_t FileSize,
+                    bool RequiresNullTerminator, bool IsVolatile) {
+  assert(FD != -1 && "cannot get buffer for closed file");
+  return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator,
+                                   IsVolatile);
+}
+
+std::error_code RealFile::close() {
+  std::error_code EC = sys::Process::SafelyCloseFileDescriptor(FD);
+  FD = -1;
+  return EC;
+}
+
+namespace {
+
+/// The file system according to your operating system.
+class RealFileSystem : public FileSystem {
+public:
+  ErrorOr<Status> status(const Twine &Path) override;
+  ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
+  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+
+  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
+  std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
+  std::error_code getRealPath(const Twine &Path,
+                              SmallVectorImpl<char> &Output) const override;
+
+private:
+  mutable std::mutex CWDMutex;
+  mutable std::string CWDCache;
+};
+
+} // namespace
+
+ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
+  sys::fs::file_status RealStatus;
+  if (std::error_code EC = sys::fs::status(Path, RealStatus))
+    return EC;
+  return Status::copyWithNewName(RealStatus, Path.str());
+}
+
+ErrorOr<std::unique_ptr<File>>
+RealFileSystem::openFileForRead(const Twine &Name) {
+  int FD;
+  SmallString<256> RealName;
+  if (std::error_code EC =
+          sys::fs::openFileForRead(Name, FD, sys::fs::OF_None, &RealName))
+    return EC;
+  return std::unique_ptr<File>(new RealFile(FD, Name.str(), RealName.str()));
+}
+
+llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
+  std::lock_guard<std::mutex> Lock(CWDMutex);
+  if (!CWDCache.empty())
+    return CWDCache;
+  SmallString<256> Dir;
+  if (std::error_code EC = llvm::sys::fs::current_path(Dir))
+    return EC;
+  CWDCache = Dir.str();
+  return CWDCache;
+}
+
+std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
+  // FIXME: chdir is thread hostile; on the other hand, creating the same
+  // behavior as chdir is complex: chdir resolves the path once, thus
+  // guaranteeing that all subsequent relative path operations work
+  // on the same path the original chdir resulted in. This makes a
+  // difference for example on network filesystems, where symlinks might be
+  // switched during runtime of the tool. Fixing this depends on having a
+  // file system abstraction that allows openat() style interactions.
+  if (auto EC = llvm::sys::fs::set_current_path(Path))
+    return EC;
+
+  // Invalidate cache.
+  std::lock_guard<std::mutex> Lock(CWDMutex);
+  CWDCache.clear();
+  return std::error_code();
+}
+
+std::error_code
+RealFileSystem::getRealPath(const Twine &Path,
+                            SmallVectorImpl<char> &Output) const {
+  return llvm::sys::fs::real_path(Path, Output);
+}
+
+IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
+  static IntrusiveRefCntPtr<FileSystem> FS = new RealFileSystem();
+  return FS;
+}
+
+namespace {
+
+class RealFSDirIter : public llvm::vfs::detail::DirIterImpl {
+  llvm::sys::fs::directory_iterator Iter;
+
+public:
+  RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
+    if (Iter != llvm::sys::fs::directory_iterator())
+      CurrentEntry = directory_entry(Iter->path(), Iter->type());
+  }
+
+  std::error_code increment() override {
+    std::error_code EC;
+    Iter.increment(EC);
+    CurrentEntry = (Iter == llvm::sys::fs::directory_iterator())
+                       ? directory_entry()
+                       : directory_entry(Iter->path(), Iter->type());
+    return EC;
+  }
+};
+
+} // namespace
+
+directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
+                                             std::error_code &EC) {
+  return directory_iterator(std::make_shared<RealFSDirIter>(Dir, EC));
+}
+
+//===-----------------------------------------------------------------------===/
+// OverlayFileSystem implementation
+//===-----------------------------------------------------------------------===/
+
+OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) {
+  FSList.push_back(std::move(BaseFS));
+}
+
+void OverlayFileSystem::pushOverlay(IntrusiveRefCntPtr<FileSystem> FS) {
+  FSList.push_back(FS);
+  // Synchronize added file systems by duplicating the working directory from
+  // the first one in the list.
+  FS->setCurrentWorkingDirectory(getCurrentWorkingDirectory().get());
+}
+
+ErrorOr<Status> OverlayFileSystem::status(const Twine &Path) {
+  // FIXME: handle symlinks that cross file systems
+  for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
+    ErrorOr<Status> Status = (*I)->status(Path);
+    if (Status || Status.getError() != llvm::errc::no_such_file_or_directory)
+      return Status;
+  }
+  return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+ErrorOr<std::unique_ptr<File>>
+OverlayFileSystem::openFileForRead(const llvm::Twine &Path) {
+  // FIXME: handle symlinks that cross file systems
+  for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) {
+    auto Result = (*I)->openFileForRead(Path);
+    if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
+      return Result;
+  }
+  return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+llvm::ErrorOr<std::string>
+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
+OverlayFileSystem::getRealPath(const Twine &Path,
+                               SmallVectorImpl<char> &Output) const {
+  for (auto &FS : FSList)
+    if (FS->exists(Path))
+      return FS->getRealPath(Path, Output);
+  return errc::no_such_file_or_directory;
+}
+
+llvm::vfs::detail::DirIterImpl::~DirIterImpl() = default;
+
+namespace {
+
+class OverlayFSDirIterImpl : public llvm::vfs::detail::DirIterImpl {
+  OverlayFileSystem &Overlays;
+  std::string Path;
+  OverlayFileSystem::iterator CurrentFS;
+  directory_iterator CurrentDirIter;
+  llvm::StringSet<> SeenNames;
+
+  std::error_code incrementFS() {
+    assert(CurrentFS != Overlays.overlays_end() && "incrementing past end");
+    ++CurrentFS;
+    for (auto E = Overlays.overlays_end(); CurrentFS != E; ++CurrentFS) {
+      std::error_code EC;
+      CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
+      if (EC && EC != errc::no_such_file_or_directory)
+        return EC;
+      if (CurrentDirIter != directory_iterator())
+        break; // found
+    }
+    return {};
+  }
+
+  std::error_code incrementDirIter(bool IsFirstTime) {
+    assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&
+           "incrementing past end");
+    std::error_code EC;
+    if (!IsFirstTime)
+      CurrentDirIter.increment(EC);
+    if (!EC && CurrentDirIter == directory_iterator())
+      EC = incrementFS();
+    return EC;
+  }
+
+  std::error_code incrementImpl(bool IsFirstTime) {
+    while (true) {
+      std::error_code EC = incrementDirIter(IsFirstTime);
+      if (EC || CurrentDirIter == directory_iterator()) {
+        CurrentEntry = directory_entry();
+        return EC;
+      }
+      CurrentEntry = *CurrentDirIter;
+      StringRef Name = llvm::sys::path::filename(CurrentEntry.path());
+      if (SeenNames.insert(Name).second)
+        return EC; // name not seen before
+    }
+    llvm_unreachable("returned above");
+  }
+
+public:
+  OverlayFSDirIterImpl(const Twine &Path, OverlayFileSystem &FS,
+                       std::error_code &EC)
+      : Overlays(FS), Path(Path.str()), CurrentFS(Overlays.overlays_begin()) {
+    CurrentDirIter = (*CurrentFS)->dir_begin(Path, EC);
+    EC = incrementImpl(true);
+  }
+
+  std::error_code increment() override { return incrementImpl(false); }
+};
+
+} // namespace
+
+directory_iterator OverlayFileSystem::dir_begin(const Twine &Dir,
+                                                std::error_code &EC) {
+  return directory_iterator(
+      std::make_shared<OverlayFSDirIterImpl>(Dir, *this, EC));
+}
+
+namespace llvm {
+namespace vfs {
+
+namespace detail {
+
+enum InMemoryNodeKind { IME_File, IME_Directory, IME_HardLink };
+
+/// The in memory file system is a tree of Nodes. Every node can either be a
+/// file , hardlink or a directory.
+class InMemoryNode {
+  InMemoryNodeKind Kind;
+  std::string FileName;
+
+public:
+  InMemoryNode(llvm::StringRef FileName, InMemoryNodeKind Kind)
+      : Kind(Kind), FileName(llvm::sys::path::filename(FileName)) {}
+  virtual ~InMemoryNode() = default;
+
+  /// Get the filename of this node (the name without the directory part).
+  StringRef getFileName() const { return FileName; }
+  InMemoryNodeKind getKind() const { return Kind; }
+  virtual std::string toString(unsigned Indent) const = 0;
+};
+
+class InMemoryFile : public InMemoryNode {
+  Status Stat;
+  std::unique_ptr<llvm::MemoryBuffer> Buffer;
+
+public:
+  InMemoryFile(Status Stat, std::unique_ptr<llvm::MemoryBuffer> Buffer)
+      : InMemoryNode(Stat.getName(), IME_File), Stat(std::move(Stat)),
+        Buffer(std::move(Buffer)) {}
+
+  /// 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);
+  }
+  llvm::MemoryBuffer *getBuffer() const { return Buffer.get(); }
+
+  std::string toString(unsigned Indent) const override {
+    return (std::string(Indent, ' ') + Stat.getName() + "\n").str();
+  }
+
+  static bool classof(const InMemoryNode *N) {
+    return N->getKind() == IME_File;
+  }
+};
+
+namespace {
+
+class InMemoryHardLink : public InMemoryNode {
+  const InMemoryFile &ResolvedFile;
+
+public:
+  InMemoryHardLink(StringRef Path, const InMemoryFile &ResolvedFile)
+      : InMemoryNode(Path, IME_HardLink), ResolvedFile(ResolvedFile) {}
+  const InMemoryFile &getResolvedFile() const { return ResolvedFile; }
+
+  std::string toString(unsigned Indent) const override {
+    return std::string(Indent, ' ') + "HardLink to -> " +
+           ResolvedFile.toString(0);
+  }
+
+  static bool classof(const InMemoryNode *N) {
+    return N->getKind() == IME_HardLink;
+  }
+};
+
+/// 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 {
+  const InMemoryFile &Node;
+  /// The name to use when returning a Status for this file.
+  std::string RequestedName;
+
+public:
+  explicit InMemoryFileAdaptor(const InMemoryFile &Node,
+                               std::string RequestedName)
+      : Node(Node), RequestedName(std::move(RequestedName)) {}
+
+  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,
+            bool IsVolatile) override {
+    llvm::MemoryBuffer *Buf = Node.getBuffer();
+    return llvm::MemoryBuffer::getMemBuffer(
+        Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
+  }
+
+  std::error_code close() override { return {}; }
+};
+} // namespace
+
+class InMemoryDirectory : public InMemoryNode {
+  Status Stat;
+  llvm::StringMap<std::unique_ptr<InMemoryNode>> Entries;
+
+public:
+  InMemoryDirectory(Status Stat)
+      : InMemoryNode(Stat.getName(), IME_Directory), Stat(std::move(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);
+  }
+  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();
+  }
+
+  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, ' ') + Stat.getName() + "\n").str();
+    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 {
+Status getNodeStatus(const InMemoryNode *Node, StringRef RequestedName) {
+  if (auto Dir = dyn_cast<detail::InMemoryDirectory>(Node))
+    return Dir->getStatus(RequestedName);
+  if (auto File = dyn_cast<detail::InMemoryFile>(Node))
+    return File->getStatus(RequestedName);
+  if (auto Link = dyn_cast<detail::InMemoryHardLink>(Node))
+    return Link->getResolvedFile().getStatus(RequestedName);
+  llvm_unreachable("Unknown node type");
+}
+} // namespace
+} // namespace detail
+
+InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
+    : Root(new detail::InMemoryDirectory(
+          Status("", getNextVirtualUniqueID(), llvm::sys::TimePoint<>(), 0, 0,
+                 0, llvm::sys::fs::file_type::directory_file,
+                 llvm::sys::fs::perms::all_all))),
+      UseNormalizedPaths(UseNormalizedPaths) {}
+
+InMemoryFileSystem::~InMemoryFileSystem() = default;
+
+std::string InMemoryFileSystem::toString() const {
+  return Root->toString(/*Indent=*/0);
+}
+
+bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
+                                 std::unique_ptr<llvm::MemoryBuffer> Buffer,
+                                 Optional<uint32_t> User,
+                                 Optional<uint32_t> Group,
+                                 Optional<llvm::sys::fs::file_type> Type,
+                                 Optional<llvm::sys::fs::perms> Perms,
+                                 const detail::InMemoryFile *HardLinkTarget) {
+  SmallString<128> Path;
+  P.toVector(Path);
+
+  // Fix up relative paths. This just prepends the current working directory.
+  std::error_code EC = makeAbsolute(Path);
+  assert(!EC);
+  (void)EC;
+
+  if (useNormalizedPaths())
+    llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+
+  if (Path.empty())
+    return false;
+
+  detail::InMemoryDirectory *Dir = Root.get();
+  auto I = llvm::sys::path::begin(Path), E = sys::path::end(Path);
+  const auto ResolvedUser = User.getValueOr(0);
+  const auto ResolvedGroup = Group.getValueOr(0);
+  const auto ResolvedType = Type.getValueOr(sys::fs::file_type::regular_file);
+  const auto ResolvedPerms = Perms.getValueOr(sys::fs::all_all);
+  assert(!(HardLinkTarget && Buffer) && "HardLink cannot have a buffer");
+  // Any intermediate directories we create should be accessible by
+  // the owner, even if Perms says otherwise for the final path.
+  const auto NewDirectoryPerms = ResolvedPerms | sys::fs::owner_all;
+  while (true) {
+    StringRef Name = *I;
+    detail::InMemoryNode *Node = Dir->getChild(Name);
+    ++I;
+    if (!Node) {
+      if (I == E) {
+        // End of the path.
+        std::unique_ptr<detail::InMemoryNode> Child;
+        if (HardLinkTarget)
+          Child.reset(new detail::InMemoryHardLink(P.str(), *HardLinkTarget));
+        else {
+          // Create a new file or directory.
+          Status Stat(P.str(), getNextVirtualUniqueID(),
+                      llvm::sys::toTimePoint(ModificationTime), ResolvedUser,
+                      ResolvedGroup, Buffer->getBufferSize(), ResolvedType,
+                      ResolvedPerms);
+          if (ResolvedType == sys::fs::file_type::directory_file) {
+            Child.reset(new detail::InMemoryDirectory(std::move(Stat)));
+          } else {
+            Child.reset(
+                new detail::InMemoryFile(std::move(Stat), std::move(Buffer)));
+          }
+        }
+        Dir->addChild(Name, std::move(Child));
+        return true;
+      }
+
+      // Create a new directory. Use the path up to here.
+      Status Stat(
+          StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
+          getNextVirtualUniqueID(), llvm::sys::toTimePoint(ModificationTime),
+          ResolvedUser, ResolvedGroup, 0, sys::fs::file_type::directory_file,
+          NewDirectoryPerms);
+      Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
+          Name, llvm::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
+      continue;
+    }
+
+    if (auto *NewDir = dyn_cast<detail::InMemoryDirectory>(Node)) {
+      Dir = NewDir;
+    } else {
+      assert((isa<detail::InMemoryFile>(Node) ||
+              isa<detail::InMemoryHardLink>(Node)) &&
+             "Must be either file, hardlink or directory!");
+
+      // Trying to insert a directory in place of a file.
+      if (I != E)
+        return false;
+
+      // Return false only if the new file is different from the existing one.
+      if (auto Link = dyn_cast<detail::InMemoryHardLink>(Node)) {
+        return Link->getResolvedFile().getBuffer()->getBuffer() ==
+               Buffer->getBuffer();
+      }
+      return cast<detail::InMemoryFile>(Node)->getBuffer()->getBuffer() ==
+             Buffer->getBuffer();
+    }
+  }
+}
+
+bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
+                                 std::unique_ptr<llvm::MemoryBuffer> Buffer,
+                                 Optional<uint32_t> User,
+                                 Optional<uint32_t> Group,
+                                 Optional<llvm::sys::fs::file_type> Type,
+                                 Optional<llvm::sys::fs::perms> Perms) {
+  return addFile(P, ModificationTime, std::move(Buffer), User, Group, Type,
+                 Perms, /*HardLinkTarget=*/nullptr);
+}
+
+bool InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime,
+                                      llvm::MemoryBuffer *Buffer,
+                                      Optional<uint32_t> User,
+                                      Optional<uint32_t> Group,
+                                      Optional<llvm::sys::fs::file_type> Type,
+                                      Optional<llvm::sys::fs::perms> Perms) {
+  return addFile(P, ModificationTime,
+                 llvm::MemoryBuffer::getMemBuffer(
+                     Buffer->getBuffer(), Buffer->getBufferIdentifier()),
+                 std::move(User), std::move(Group), std::move(Type),
+                 std::move(Perms));
+}
+
+static ErrorOr<const detail::InMemoryNode *>
+lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir,
+                   const Twine &P) {
+  SmallString<128> Path;
+  P.toVector(Path);
+
+  // Fix up relative paths. This just prepends the current working directory.
+  std::error_code EC = FS.makeAbsolute(Path);
+  assert(!EC);
+  (void)EC;
+
+  if (FS.useNormalizedPaths())
+    llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+
+  if (Path.empty())
+    return Dir;
+
+  auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
+  while (true) {
+    detail::InMemoryNode *Node = Dir->getChild(*I);
+    ++I;
+    if (!Node)
+      return errc::no_such_file_or_directory;
+
+    // Return the file if it's at the end of the path.
+    if (auto File = dyn_cast<detail::InMemoryFile>(Node)) {
+      if (I == E)
+        return File;
+      return errc::no_such_file_or_directory;
+    }
+
+    // If Node is HardLink then return the resolved file.
+    if (auto File = dyn_cast<detail::InMemoryHardLink>(Node)) {
+      if (I == E)
+        return &File->getResolvedFile();
+      return errc::no_such_file_or_directory;
+    }
+    // Traverse directories.
+    Dir = cast<detail::InMemoryDirectory>(Node);
+    if (I == E)
+      return Dir;
+  }
+}
+
+bool InMemoryFileSystem::addHardLink(const Twine &FromPath,
+                                     const Twine &ToPath) {
+  auto FromNode = lookupInMemoryNode(*this, Root.get(), FromPath);
+  auto ToNode = lookupInMemoryNode(*this, Root.get(), ToPath);
+  // FromPath must not have been added before. ToPath must have been added
+  // before. Resolved ToPath must be a File.
+  if (!ToNode || FromNode || !isa<detail::InMemoryFile>(*ToNode))
+    return false;
+  return this->addFile(FromPath, 0, nullptr, None, None, None, None,
+                       cast<detail::InMemoryFile>(*ToNode));
+}
+
+llvm::ErrorOr<Status> InMemoryFileSystem::status(const Twine &Path) {
+  auto Node = lookupInMemoryNode(*this, Root.get(), Path);
+  if (Node)
+    return detail::getNodeStatus(*Node, Path.str());
+  return Node.getError();
+}
+
+llvm::ErrorOr<std::unique_ptr<File>>
+InMemoryFileSystem::openFileForRead(const Twine &Path) {
+  auto Node = lookupInMemoryNode(*this, Root.get(), Path);
+  if (!Node)
+    return Node.getError();
+
+  // 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, Path.str()));
+
+  // FIXME: errc::not_a_file?
+  return make_error_code(llvm::errc::invalid_argument);
+}
+
+namespace {
+
+/// Adaptor from InMemoryDir::iterator to directory_iterator.
+class InMemoryDirIterator : public llvm::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());
+      sys::fs::file_type Type;
+      switch (I->second->getKind()) {
+      case detail::IME_File:
+      case detail::IME_HardLink:
+        Type = sys::fs::file_type::regular_file;
+        break;
+      case detail::IME_Directory:
+        Type = sys::fs::file_type::directory_file;
+        break;
+      }
+      CurrentEntry = directory_entry(Path.str(), Type);
+    } else {
+      // When we're at the end, make CurrentEntry invalid and DirIterImpl will
+      // do the rest.
+      CurrentEntry = directory_entry();
+    }
+  }
+
+public:
+  InMemoryDirIterator() = default;
+
+  explicit InMemoryDirIterator(const detail::InMemoryDirectory &Dir,
+                               std::string RequestedDirName)
+      : I(Dir.begin()), E(Dir.end()),
+        RequestedDirName(std::move(RequestedDirName)) {
+    setCurrentEntry();
+  }
+
+  std::error_code increment() override {
+    ++I;
+    setCurrentEntry();
+    return {};
+  }
+};
+
+} // namespace
+
+directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir,
+                                                 std::error_code &EC) {
+  auto Node = lookupInMemoryNode(*this, Root.get(), Dir);
+  if (!Node) {
+    EC = Node.getError();
+    return directory_iterator(std::make_shared<InMemoryDirIterator>());
+  }
+
+  if (auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node))
+    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>());
+}
+
+std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) {
+  SmallString<128> Path;
+  P.toVector(Path);
+
+  // Fix up relative paths. This just prepends the current working directory.
+  std::error_code EC = makeAbsolute(Path);
+  assert(!EC);
+  (void)EC;
+
+  if (useNormalizedPaths())
+    llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+
+  if (!Path.empty())
+    WorkingDirectory = Path.str();
+  return {};
+}
+
+std::error_code
+InMemoryFileSystem::getRealPath(const Twine &Path,
+                                SmallVectorImpl<char> &Output) const {
+  auto CWD = getCurrentWorkingDirectory();
+  if (!CWD || CWD->empty())
+    return errc::operation_not_permitted;
+  Path.toVector(Output);
+  if (auto EC = makeAbsolute(Output))
+    return EC;
+  llvm::sys::path::remove_dots(Output, /*remove_dot_dot=*/true);
+  return {};
+}
+
+} // namespace vfs
+} // namespace llvm
+
+//===-----------------------------------------------------------------------===/
+// RedirectingFileSystem implementation
+//===-----------------------------------------------------------------------===/
+
+namespace {
+
+enum EntryKind { EK_Directory, EK_File };
+
+/// A single file or directory in the VFS.
+class Entry {
+  EntryKind Kind;
+  std::string Name;
+
+public:
+  Entry(EntryKind K, StringRef Name) : Kind(K), Name(Name) {}
+  virtual ~Entry() = default;
+
+  StringRef getName() const { return Name; }
+  EntryKind getKind() const { return Kind; }
+};
+
+class RedirectingDirectoryEntry : public Entry {
+  std::vector<std::unique_ptr<Entry>> Contents;
+  Status S;
+
+public:
+  RedirectingDirectoryEntry(StringRef Name,
+                            std::vector<std::unique_ptr<Entry>> Contents,
+                            Status S)
+      : Entry(EK_Directory, Name), Contents(std::move(Contents)),
+        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(); }
+
+  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; }
+};
+
+class RedirectingFileEntry : public Entry {
+public:
+  enum NameKind { NK_NotSet, 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; }
+
+  /// 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; }
+};
+
+class VFSFromYamlDirIterImpl : public llvm::vfs::detail::DirIterImpl {
+  std::string Dir;
+  RedirectingDirectoryEntry::iterator Current, End;
+
+  std::error_code incrementImpl();
+
+public:
+  VFSFromYamlDirIterImpl(const Twine &Path,
+                         RedirectingDirectoryEntry::iterator Begin,
+                         RedirectingDirectoryEntry::iterator End,
+                         std::error_code &EC);
+
+  std::error_code increment() override;
+};
+
+/// A virtual file system parsed from a YAML file.
+///
+/// Currently, this class allows creating virtual directories and mapping
+/// virtual file paths to existing external files, available in \c ExternalFS.
+///
+/// The basic structure of the parsed file is:
+/// \verbatim
+/// {
+///   'version': <version number>,
+///   <optional configuration>
+///   'roots': [
+///              <directory entries>
+///            ]
+/// }
+/// \endverbatim
+///
+/// All configuration options are optional.
+///   'case-sensitive': <boolean, default=true>
+///   'use-external-names': <boolean, default=true>
+///   'overlay-relative': <boolean, default=false>
+///   'ignore-non-existent-contents': <boolean, default=true>
+///
+/// Virtual directories are represented as
+/// \verbatim
+/// {
+///   'type': 'directory',
+///   'name': <string>,
+///   'contents': [ <file or directory entries> ]
+/// }
+/// \endverbatim
+///
+/// The default attributes for virtual directories are:
+/// \verbatim
+/// MTime = now() when created
+/// Perms = 0777
+/// User = Group = 0
+/// Size = 0
+/// UniqueID = unspecified unique value
+/// \endverbatim
+///
+/// Re-mapped files are represented as
+/// \verbatim
+/// {
+///   'type': 'file',
+///   'name': <string>,
+///   'use-external-name': <boolean> # Optional
+///   'external-contents': <path to external file>
+/// }
+/// \endverbatim
+///
+/// and inherit their attributes from the external contents.
+///
+/// In both cases, the 'name' field may contain multiple path components (e.g.
+/// /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;
+
+  /// 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.
+  std::string ExternalContentsPrefixDir;
+
+  /// @name Configuration
+  /// @{
+
+  /// Whether to perform case-sensitive comparisons.
+  ///
+  /// Currently, case-insensitive matching only works correctly with ASCII.
+  bool CaseSensitive = true;
+
+  /// IsRelativeOverlay marks whether a ExternalContentsPrefixDir path must
+  /// be prefixed in every 'external-contents' when reading from YAML files.
+  bool IsRelativeOverlay = false;
+
+  /// Whether to use to use the value of 'external-contents' for the
+  /// names of files.  This global value is overridable on a per-file basis.
+  bool UseExternalNames = true;
+
+  /// Whether an invalid path obtained via 'external-contents' should
+  /// cause iteration on the VFS to stop. If 'true', the VFS should ignore
+  /// the entry and continue with the next. Allows YAML files to be shared
+  /// across multiple compiler invocations regardless of prior existent
+  /// paths in 'external-contents'. This global value is overridable on a
+  /// per-file basis.
+  bool IgnoreNonExistentContents = true;
+  /// @}
+
+  /// Virtual file paths and external files could be canonicalized without "..",
+  /// "." and "./" in their paths. FIXME: some unittests currently fail on
+  /// win32 when using remove_dots and remove_leading_dotslash on paths.
+  bool UseCanonicalizedPaths =
+#ifdef _WIN32
+      false;
+#else
+      true;
+#endif
+
+private:
+  RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
+      : ExternalFS(std::move(ExternalFS)) {}
+
+  /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly
+  /// recursing into the contents of \p From if it is a directory.
+  ErrorOr<Entry *> lookupPath(sys::path::const_iterator Start,
+                              sys::path::const_iterator End, Entry *From);
+
+  /// Get the status of a given an \c Entry.
+  ErrorOr<Status> status(const Twine &Path, Entry *E);
+
+public:
+  /// Looks up \p Path in \c Roots.
+  ErrorOr<Entry *> lookupPath(const Twine &Path);
+
+  /// Parses \p Buffer, which is expected to be in YAML format and
+  /// returns a virtual file system representing its contents.
+  static RedirectingFileSystem *
+  create(std::unique_ptr<MemoryBuffer> Buffer,
+         SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
+         void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
+
+  ErrorOr<Status> status(const Twine &Path) override;
+  ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
+
+  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+    return ExternalFS->getCurrentWorkingDirectory();
+  }
+
+  std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
+    return ExternalFS->setCurrentWorkingDirectory(Path);
+  }
+
+  directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override {
+    ErrorOr<Entry *> E = lookupPath(Dir);
+    if (!E) {
+      EC = E.getError();
+      return {};
+    }
+    ErrorOr<Status> S = status(Dir, *E);
+    if (!S) {
+      EC = S.getError();
+      return {};
+    }
+    if (!S->isDirectory()) {
+      EC = std::error_code(static_cast<int>(errc::not_a_directory),
+                           std::system_category());
+      return {};
+    }
+
+    auto *D = cast<RedirectingDirectoryEntry>(*E);
+    return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(
+        Dir, D->contents_begin(), D->contents_end(), EC));
+  }
+
+  void setExternalContentsPrefixDir(StringRef PrefixDir) {
+    ExternalContentsPrefixDir = PrefixDir.str();
+  }
+
+  StringRef getExternalContentsPrefixDir() const {
+    return ExternalContentsPrefixDir;
+  }
+
+  bool ignoreNonExistentContents() const { return IgnoreNonExistentContents; }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  LLVM_DUMP_METHOD void dump() const {
+    for (const auto &Root : Roots)
+      dumpEntry(Root.get());
+  }
+
+  LLVM_DUMP_METHOD void dumpEntry(Entry *E, int NumSpaces = 0) const {
+    StringRef Name = E->getName();
+    for (int i = 0, e = NumSpaces; i < e; ++i)
+      dbgs() << " ";
+    dbgs() << "'" << Name.str().c_str() << "'"
+           << "\n";
+
+    if (E->getKind() == EK_Directory) {
+      auto *DE = dyn_cast<RedirectingDirectoryEntry>(E);
+      assert(DE && "Should be a directory");
+
+      for (std::unique_ptr<Entry> &SubEntry :
+           llvm::make_range(DE->contents_begin(), DE->contents_end()))
+        dumpEntry(SubEntry.get(), NumSpaces + 2);
+    }
+  }
+#endif
+};
+
+/// A helper class to hold the common YAML parsing state.
+class RedirectingFileSystemParser {
+  yaml::Stream &Stream;
+
+  void error(yaml::Node *N, const Twine &Msg) { Stream.printError(N, Msg); }
+
+  // false on error
+  bool parseScalarString(yaml::Node *N, StringRef &Result,
+                         SmallVectorImpl<char> &Storage) {
+    const auto *S = dyn_cast<yaml::ScalarNode>(N);
+
+    if (!S) {
+      error(N, "expected string");
+      return false;
+    }
+    Result = S->getValue(Storage);
+    return true;
+  }
+
+  // false on error
+  bool parseScalarBool(yaml::Node *N, bool &Result) {
+    SmallString<5> Storage;
+    StringRef Value;
+    if (!parseScalarString(N, Value, Storage))
+      return false;
+
+    if (Value.equals_lower("true") || Value.equals_lower("on") ||
+        Value.equals_lower("yes") || Value == "1") {
+      Result = true;
+      return true;
+    } else if (Value.equals_lower("false") || Value.equals_lower("off") ||
+               Value.equals_lower("no") || Value == "0") {
+      Result = false;
+      return true;
+    }
+
+    error(N, "expected boolean value");
+    return false;
+  }
+
+  struct KeyStatus {
+    bool Required;
+    bool Seen = false;
+
+    KeyStatus(bool Required = false) : Required(Required) {}
+  };
+
+  using KeyStatusPair = std::pair<StringRef, KeyStatus>;
+
+  // false on error
+  bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode, StringRef Key,
+                                  DenseMap<StringRef, KeyStatus> &Keys) {
+    if (!Keys.count(Key)) {
+      error(KeyNode, "unknown key");
+      return false;
+    }
+    KeyStatus &S = Keys[Key];
+    if (S.Seen) {
+      error(KeyNode, Twine("duplicate key '") + Key + "'");
+      return false;
+    }
+    S.Seen = true;
+    return true;
+  }
+
+  // false on error
+  bool checkMissingKeys(yaml::Node *Obj, DenseMap<StringRef, KeyStatus> &Keys) {
+    for (const auto &I : Keys) {
+      if (I.second.Required && !I.second.Seen) {
+        error(Obj, Twine("missing key '") + I.first + "'");
+        return false;
+      }
+    }
+    return true;
+  }
+
+  Entry *lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name,
+                             Entry *ParentEntry = nullptr) {
+    if (!ParentEntry) { // Look for a existent root
+      for (const auto &Root : FS->Roots) {
+        if (Name.equals(Root->getName())) {
+          ParentEntry = Root.get();
+          return ParentEntry;
+        }
+      }
+    } else { // Advance to the next component
+      auto *DE = dyn_cast<RedirectingDirectoryEntry>(ParentEntry);
+      for (std::unique_ptr<Entry> &Content :
+           llvm::make_range(DE->contents_begin(), DE->contents_end())) {
+        auto *DirContent = dyn_cast<RedirectingDirectoryEntry>(Content.get());
+        if (DirContent && Name.equals(Content->getName()))
+          return DirContent;
+      }
+    }
+
+    // ... or create a new one
+    std::unique_ptr<Entry> E = llvm::make_unique<RedirectingDirectoryEntry>(
+        Name,
+        Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
+               0, 0, 0, file_type::directory_file, sys::fs::all_all));
+
+    if (!ParentEntry) { // Add a new root to the overlay
+      FS->Roots.push_back(std::move(E));
+      ParentEntry = FS->Roots.back().get();
+      return ParentEntry;
+    }
+
+    auto *DE = dyn_cast<RedirectingDirectoryEntry>(ParentEntry);
+    DE->addContent(std::move(E));
+    return DE->getLastContent();
+  }
+
+  void uniqueOverlayTree(RedirectingFileSystem *FS, Entry *SrcE,
+                         Entry *NewParentE = nullptr) {
+    StringRef Name = SrcE->getName();
+    switch (SrcE->getKind()) {
+    case EK_Directory: {
+      auto *DE = dyn_cast<RedirectingDirectoryEntry>(SrcE);
+      assert(DE && "Must be a directory");
+      // Empty directories could be present in the YAML as a way to
+      // describe a file for a current directory after some of its subdir
+      // is parsed. This only leads to redundant walks, ignore it.
+      if (!Name.empty())
+        NewParentE = lookupOrCreateEntry(FS, Name, NewParentE);
+      for (std::unique_ptr<Entry> &SubEntry :
+           llvm::make_range(DE->contents_begin(), DE->contents_end()))
+        uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
+      break;
+    }
+    case EK_File: {
+      auto *FE = dyn_cast<RedirectingFileEntry>(SrcE);
+      assert(FE && "Must be a file");
+      assert(NewParentE && "Parent entry must exist");
+      auto *DE = dyn_cast<RedirectingDirectoryEntry>(NewParentE);
+      DE->addContent(llvm::make_unique<RedirectingFileEntry>(
+          Name, FE->getExternalContentsPath(), FE->getUseName()));
+      break;
+    }
+    }
+  }
+
+  std::unique_ptr<Entry> parseEntry(yaml::Node *N, RedirectingFileSystem *FS,
+                                    bool IsRootEntry) {
+    auto *M = dyn_cast<yaml::MappingNode>(N);
+    if (!M) {
+      error(N, "expected mapping node for file or directory entry");
+      return nullptr;
+    }
+
+    KeyStatusPair Fields[] = {
+        KeyStatusPair("name", true),
+        KeyStatusPair("type", true),
+        KeyStatusPair("contents", false),
+        KeyStatusPair("external-contents", false),
+        KeyStatusPair("use-external-name", false),
+    };
+
+    DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
+
+    bool HasContents = false; // external or otherwise
+    std::vector<std::unique_ptr<Entry>> EntryArrayContents;
+    std::string ExternalContentsPath;
+    std::string Name;
+    yaml::Node *NameValueNode;
+    auto UseExternalName = RedirectingFileEntry::NK_NotSet;
+    EntryKind Kind;
+
+    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))
+        return nullptr;
+
+      if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
+        return nullptr;
+
+      StringRef Value;
+      if (Key == "name") {
+        if (!parseScalarString(I.getValue(), Value, Buffer))
+          return nullptr;
+
+        NameValueNode = I.getValue();
+        if (FS->UseCanonicalizedPaths) {
+          SmallString<256> Path(Value);
+          // Guarantee that old YAML files containing paths with ".." and "."
+          // are properly canonicalized before read into the VFS.
+          Path = sys::path::remove_leading_dotslash(Path);
+          sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+          Name = Path.str();
+        } else {
+          Name = Value;
+        }
+      } else if (Key == "type") {
+        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'");
+          return nullptr;
+        }
+      } else if (Key == "contents") {
+        if (HasContents) {
+          error(I.getKey(),
+                "entry already has 'contents' or 'external-contents'");
+          return nullptr;
+        }
+        HasContents = true;
+        auto *Contents = dyn_cast<yaml::SequenceNode>(I.getValue());
+        if (!Contents) {
+          // FIXME: this is only for directories, what about files?
+          error(I.getValue(), "expected array");
+          return nullptr;
+        }
+
+        for (auto &I : *Contents) {
+          if (std::unique_ptr<Entry> E =
+                  parseEntry(&I, FS, /*IsRootEntry*/ false))
+            EntryArrayContents.push_back(std::move(E));
+          else
+            return nullptr;
+        }
+      } else if (Key == "external-contents") {
+        if (HasContents) {
+          error(I.getKey(),
+                "entry already has 'contents' or 'external-contents'");
+          return nullptr;
+        }
+        HasContents = true;
+        if (!parseScalarString(I.getValue(), Value, Buffer))
+          return nullptr;
+
+        SmallString<256> FullPath;
+        if (FS->IsRelativeOverlay) {
+          FullPath = FS->getExternalContentsPrefixDir();
+          assert(!FullPath.empty() &&
+                 "External contents prefix directory must exist");
+          llvm::sys::path::append(FullPath, Value);
+        } else {
+          FullPath = Value;
+        }
+
+        if (FS->UseCanonicalizedPaths) {
+          // Guarantee that old YAML files containing paths with ".." and "."
+          // are properly canonicalized before read into the VFS.
+          FullPath = sys::path::remove_leading_dotslash(FullPath);
+          sys::path::remove_dots(FullPath, /*remove_dot_dot=*/true);
+        }
+        ExternalContentsPath = FullPath.str();
+      } else if (Key == "use-external-name") {
+        bool Val;
+        if (!parseScalarBool(I.getValue(), Val))
+          return nullptr;
+        UseExternalName = Val ? RedirectingFileEntry::NK_External
+                              : RedirectingFileEntry::NK_Virtual;
+      } else {
+        llvm_unreachable("key missing from Keys");
+      }
+    }
+
+    if (Stream.failed())
+      return nullptr;
+
+    // check for missing keys
+    if (!HasContents) {
+      error(N, "missing key 'contents' or 'external-contents'");
+      return nullptr;
+    }
+    if (!checkMissingKeys(N, Keys))
+      return nullptr;
+
+    // check invalid configuration
+    if (Kind == EK_Directory &&
+        UseExternalName != RedirectingFileEntry::NK_NotSet) {
+      error(N, "'use-external-name' is not supported for directories");
+      return nullptr;
+    }
+
+    if (IsRootEntry && !sys::path::is_absolute(Name)) {
+      assert(NameValueNode && "Name presence should be checked earlier");
+      error(NameValueNode,
+            "entry with relative path at the root level is not discoverable");
+      return nullptr;
+    }
+
+    // Remove trailing slash(es), being careful not to remove the root path
+    StringRef Trimmed(Name);
+    size_t RootPathLen = sys::path::root_path(Trimmed).size();
+    while (Trimmed.size() > RootPathLen &&
+           sys::path::is_separator(Trimmed.back()))
+      Trimmed = Trimmed.slice(0, Trimmed.size() - 1);
+    // Get the last component
+    StringRef LastComponent = sys::path::filename(Trimmed);
+
+    std::unique_ptr<Entry> Result;
+    switch (Kind) {
+    case EK_File:
+      Result = llvm::make_unique<RedirectingFileEntry>(
+          LastComponent, std::move(ExternalContentsPath), UseExternalName);
+      break;
+    case EK_Directory:
+      Result = llvm::make_unique<RedirectingDirectoryEntry>(
+          LastComponent, std::move(EntryArrayContents),
+          Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
+                 0, 0, 0, file_type::directory_file, sys::fs::all_all));
+      break;
+    }
+
+    StringRef Parent = sys::path::parent_path(Trimmed);
+    if (Parent.empty())
+      return Result;
+
+    // if 'name' contains multiple components, create implicit directory entries
+    for (sys::path::reverse_iterator I = sys::path::rbegin(Parent),
+                                     E = sys::path::rend(Parent);
+         I != E; ++I) {
+      std::vector<std::unique_ptr<Entry>> Entries;
+      Entries.push_back(std::move(Result));
+      Result = llvm::make_unique<RedirectingDirectoryEntry>(
+          *I, std::move(Entries),
+          Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
+                 0, 0, 0, file_type::directory_file, sys::fs::all_all));
+    }
+    return Result;
+  }
+
+public:
+  RedirectingFileSystemParser(yaml::Stream &S) : Stream(S) {}
+
+  // false on error
+  bool parse(yaml::Node *Root, RedirectingFileSystem *FS) {
+    auto *Top = dyn_cast<yaml::MappingNode>(Root);
+    if (!Top) {
+      error(Root, "expected mapping node");
+      return false;
+    }
+
+    KeyStatusPair Fields[] = {
+        KeyStatusPair("version", true),
+        KeyStatusPair("case-sensitive", false),
+        KeyStatusPair("use-external-names", false),
+        KeyStatusPair("overlay-relative", false),
+        KeyStatusPair("ignore-non-existent-contents", false),
+        KeyStatusPair("roots", true),
+    };
+
+    DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
+    std::vector<std::unique_ptr<Entry>> RootEntries;
+
+    // Parse configuration and 'roots'
+    for (auto &I : *Top) {
+      SmallString<10> KeyBuffer;
+      StringRef Key;
+      if (!parseScalarString(I.getKey(), Key, KeyBuffer))
+        return false;
+
+      if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
+        return false;
+
+      if (Key == "roots") {
+        auto *Roots = dyn_cast<yaml::SequenceNode>(I.getValue());
+        if (!Roots) {
+          error(I.getValue(), "expected array");
+          return false;
+        }
+
+        for (auto &I : *Roots) {
+          if (std::unique_ptr<Entry> E =
+                  parseEntry(&I, FS, /*IsRootEntry*/ true))
+            RootEntries.push_back(std::move(E));
+          else
+            return false;
+        }
+      } else if (Key == "version") {
+        StringRef VersionString;
+        SmallString<4> Storage;
+        if (!parseScalarString(I.getValue(), VersionString, Storage))
+          return false;
+        int Version;
+        if (VersionString.getAsInteger<int>(10, Version)) {
+          error(I.getValue(), "expected integer");
+          return false;
+        }
+        if (Version < 0) {
+          error(I.getValue(), "invalid version number");
+          return false;
+        }
+        if (Version != 0) {
+          error(I.getValue(), "version mismatch, expected 0");
+          return false;
+        }
+      } else if (Key == "case-sensitive") {
+        if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
+          return false;
+      } else if (Key == "overlay-relative") {
+        if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
+          return false;
+      } else if (Key == "use-external-names") {
+        if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
+          return false;
+      } else if (Key == "ignore-non-existent-contents") {
+        if (!parseScalarBool(I.getValue(), FS->IgnoreNonExistentContents))
+          return false;
+      } else {
+        llvm_unreachable("key missing from Keys");
+      }
+    }
+
+    if (Stream.failed())
+      return false;
+
+    if (!checkMissingKeys(Top, Keys))
+      return false;
+
+    // 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 (auto &E : RootEntries)
+      uniqueOverlayTree(FS, E.get());
+
+    return true;
+  }
+};
+
+} // 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);
+
+  SM.setDiagHandler(DiagHandler, DiagContext);
+  yaml::document_iterator DI = Stream.begin();
+  yaml::Node *Root = DI->getRoot();
+  if (DI == Stream.end() || !Root) {
+    SM.PrintMessage(SMLoc(), SourceMgr::DK_Error, "expected root node");
+    return nullptr;
+  }
+
+  RedirectingFileSystemParser P(Stream);
+
+  std::unique_ptr<RedirectingFileSystem> FS(
+      new RedirectingFileSystem(std::move(ExternalFS)));
+
+  if (!YAMLFilePath.empty()) {
+    // Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
+    // to each 'external-contents' path.
+    //
+    // Example:
+    //    -ivfsoverlay dummy.cache/vfs/vfs.yaml
+    // yields:
+    //  FS->ExternalContentsPrefixDir => /<absolute_path_to>/dummy.cache/vfs
+    //
+    SmallString<256> OverlayAbsDir = sys::path::parent_path(YAMLFilePath);
+    std::error_code EC = llvm::sys::fs::make_absolute(OverlayAbsDir);
+    assert(!EC && "Overlay dir final path must be absolute");
+    (void)EC;
+    FS->setExternalContentsPrefixDir(OverlayAbsDir);
+  }
+
+  if (!P.parse(Root, FS.get()))
+    return nullptr;
+
+  return FS.release();
+}
+
+ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) {
+  SmallString<256> Path;
+  Path_.toVector(Path);
+
+  // Handle relative paths
+  if (std::error_code EC = makeAbsolute(Path))
+    return EC;
+
+  // Canonicalize path by removing ".", "..", "./", etc components. This is
+  // a VFS request, do bot bother about symlinks in the path components
+  // but canonicalize in order to perform the correct entry search.
+  if (UseCanonicalizedPaths) {
+    Path = sys::path::remove_leading_dotslash(Path);
+    sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+  }
+
+  if (Path.empty())
+    return make_error_code(llvm::errc::invalid_argument);
+
+  sys::path::const_iterator Start = sys::path::begin(Path);
+  sys::path::const_iterator End = sys::path::end(Path);
+  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;
+  }
+  return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+ErrorOr<Entry *>
+RedirectingFileSystem::lookupPath(sys::path::const_iterator Start,
+                                  sys::path::const_iterator End, Entry *From) {
+#ifndef _WIN32
+  assert(!isTraversalComponent(*Start) &&
+         !isTraversalComponent(From->getName()) &&
+         "Paths should not contain traversal components");
+#else
+  // FIXME: this is here to support windows, remove it once canonicalized
+  // paths become globally default.
+  if (Start->equals("."))
+    ++Start;
+#endif
+
+  StringRef FromName = From->getName();
+
+  // Forward the search to the next component in case this is an empty one.
+  if (!FromName.empty()) {
+    if (CaseSensitive ? !Start->equals(FromName)
+                      : !Start->equals_lower(FromName))
+      // failure to match
+      return make_error_code(llvm::errc::no_such_file_or_directory);
+
+    ++Start;
+
+    if (Start == End) {
+      // Match!
+      return From;
+    }
+  }
+
+  auto *DE = dyn_cast<RedirectingDirectoryEntry>(From);
+  if (!DE)
+    return make_error_code(llvm::errc::not_a_directory);
+
+  for (const std::unique_ptr<Entry> &DirEntry :
+       llvm::make_range(DE->contents_begin(), DE->contents_end())) {
+    ErrorOr<Entry *> Result = lookupPath(Start, End, DirEntry.get());
+    if (Result || Result.getError() != llvm::errc::no_such_file_or_directory)
+      return Result;
+  }
+  return make_error_code(llvm::errc::no_such_file_or_directory);
+}
+
+static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames,
+                                      Status ExternalStatus) {
+  Status S = ExternalStatus;
+  if (!UseExternalNames)
+    S = Status::copyWithNewName(S, Path.str());
+  S.IsVFSMapped = true;
+  return S;
+}
+
+ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path, Entry *E) {
+  assert(E != nullptr);
+  if (auto *F = dyn_cast<RedirectingFileEntry>(E)) {
+    ErrorOr<Status> S = ExternalFS->status(F->getExternalContentsPath());
+    assert(!S || S->getName() == F->getExternalContentsPath());
+    if (S)
+      return getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
+                                     *S);
+    return S;
+  } else { // directory
+    auto *DE = cast<RedirectingDirectoryEntry>(E);
+    return Status::copyWithNewName(DE->getStatus(), Path.str());
+  }
+}
+
+ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path) {
+  ErrorOr<Entry *> Result = lookupPath(Path);
+  if (!Result)
+    return Result.getError();
+  return status(Path, *Result);
+}
+
+namespace {
+
+/// Provide a file wrapper with an overriden status.
+class FileWithFixedStatus : public File {
+  std::unique_ptr<File> InnerFile;
+  Status S;
+
+public:
+  FileWithFixedStatus(std::unique_ptr<File> InnerFile, Status S)
+      : InnerFile(std::move(InnerFile)), S(std::move(S)) {}
+
+  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(); }
+};
+
+} // namespace
+
+ErrorOr<std::unique_ptr<File>>
+RedirectingFileSystem::openFileForRead(const Twine &Path) {
+  ErrorOr<Entry *> E = lookupPath(Path);
+  if (!E)
+    return E.getError();
+
+  auto *F = dyn_cast<RedirectingFileEntry>(*E);
+  if (!F) // FIXME: errc::not_a_file?
+    return make_error_code(llvm::errc::invalid_argument);
+
+  auto Result = ExternalFS->openFileForRead(F->getExternalContentsPath());
+  if (!Result)
+    return Result;
+
+  auto ExternalStatus = (*Result)->status();
+  if (!ExternalStatus)
+    return ExternalStatus.getError();
+
+  // FIXME: Update the status with the name and VFSMapped.
+  Status S = getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
+                                     *ExternalStatus);
+  return std::unique_ptr<File>(
+      llvm::make_unique<FileWithFixedStatus>(std::move(*Result), S));
+}
+
+IntrusiveRefCntPtr<FileSystem>
+vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
+                    SourceMgr::DiagHandlerTy DiagHandler,
+                    StringRef YAMLFilePath, void *DiagContext,
+                    IntrusiveRefCntPtr<FileSystem> ExternalFS) {
+  return RedirectingFileSystem::create(std::move(Buffer), DiagHandler,
+                                       YAMLFilePath, DiagContext,
+                                       std::move(ExternalFS));
+}
+
+static void getVFSEntries(Entry *SrcE, SmallVectorImpl<StringRef> &Path,
+                          SmallVectorImpl<YAMLVFSEntry> &Entries) {
+  auto Kind = SrcE->getKind();
+  if (Kind == EK_Directory) {
+    auto *DE = dyn_cast<RedirectingDirectoryEntry>(SrcE);
+    assert(DE && "Must be a directory");
+    for (std::unique_ptr<Entry> &SubEntry :
+         llvm::make_range(DE->contents_begin(), DE->contents_end())) {
+      Path.push_back(SubEntry->getName());
+      getVFSEntries(SubEntry.get(), Path, Entries);
+      Path.pop_back();
+    }
+    return;
+  }
+
+  assert(Kind == EK_File && "Must be a EK_File");
+  auto *FE = dyn_cast<RedirectingFileEntry>(SrcE);
+  assert(FE && "Must be a file");
+  SmallString<128> VPath;
+  for (auto &Comp : Path)
+    llvm::sys::path::append(VPath, Comp);
+  Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath()));
+}
+
+void vfs::collectVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
+                             SourceMgr::DiagHandlerTy DiagHandler,
+                             StringRef YAMLFilePath,
+                             SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
+                             void *DiagContext,
+                             IntrusiveRefCntPtr<FileSystem> ExternalFS) {
+  RedirectingFileSystem *VFS = RedirectingFileSystem::create(
+      std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext,
+      std::move(ExternalFS));
+  ErrorOr<Entry *> RootE = VFS->lookupPath("/");
+  if (!RootE)
+    return;
+  SmallVector<StringRef, 8> Components;
+  Components.push_back("/");
+  getVFSEntries(*RootE, Components, CollectedEntries);
+}
+
+UniqueID vfs::getNextVirtualUniqueID() {
+  static std::atomic<unsigned> UID;
+  unsigned ID = ++UID;
+  // The following assumes that uint64_t max will never collide with a real
+  // dev_t value from the OS.
+  return UniqueID(std::numeric_limits<uint64_t>::max(), ID);
+}
+
+void YAMLVFSWriter::addFileMapping(StringRef VirtualPath, StringRef RealPath) {
+  assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute");
+  assert(sys::path::is_absolute(RealPath) && "real path not absolute");
+  assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported");
+  Mappings.emplace_back(VirtualPath, RealPath);
+}
+
+namespace {
+
+class JSONWriter {
+  llvm::raw_ostream &OS;
+  SmallVector<StringRef, 16> DirStack;
+
+  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);
+  void endDirectory();
+  void writeEntry(StringRef VPath, StringRef RPath);
+
+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);
+       IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
+    if (*IParent != *IChild)
+      return false;
+  }
+  // Have we exhausted the parent path?
+  return IParent == EParent;
+}
+
+StringRef JSONWriter::containedPart(StringRef Parent, StringRef Path) {
+  assert(!Parent.empty());
+  assert(containedIn(Parent, Path));
+  return Path.slice(Parent.size() + 1, StringRef::npos);
+}
+
+void JSONWriter::startDirectory(StringRef Path) {
+  StringRef Name =
+      DirStack.empty() ? Path : containedPart(DirStack.back(), Path);
+  DirStack.push_back(Path);
+  unsigned Indent = getDirIndent();
+  OS.indent(Indent) << "{\n";
+  OS.indent(Indent + 2) << "'type': 'directory',\n";
+  OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(Name) << "\",\n";
+  OS.indent(Indent + 2) << "'contents': [\n";
+}
+
+void JSONWriter::endDirectory() {
+  unsigned Indent = getDirIndent();
+  OS.indent(Indent + 2) << "]\n";
+  OS.indent(Indent) << "}";
+
+  DirStack.pop_back();
+}
+
+void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) {
+  unsigned Indent = getFileIndent();
+  OS.indent(Indent) << "{\n";
+  OS.indent(Indent + 2) << "'type': 'file',\n";
+  OS.indent(Indent + 2) << "'name': \"" << llvm::yaml::escape(VPath) << "\",\n";
+  OS.indent(Indent + 2) << "'external-contents': \""
+                        << llvm::yaml::escape(RPath) << "\"\n";
+  OS.indent(Indent) << "}";
+}
+
+void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
+                       Optional<bool> UseExternalNames,
+                       Optional<bool> IsCaseSensitive,
+                       Optional<bool> IsOverlayRelative,
+                       Optional<bool> IgnoreNonExistentContents,
+                       StringRef OverlayDir) {
+  using namespace llvm::sys;
+
+  OS << "{\n"
+        "  'version': 0,\n";
+  if (IsCaseSensitive.hasValue())
+    OS << "  'case-sensitive': '"
+       << (IsCaseSensitive.getValue() ? "true" : "false") << "',\n";
+  if (UseExternalNames.hasValue())
+    OS << "  'use-external-names': '"
+       << (UseExternalNames.getValue() ? "true" : "false") << "',\n";
+  bool UseOverlayRelative = false;
+  if (IsOverlayRelative.hasValue()) {
+    UseOverlayRelative = IsOverlayRelative.getValue();
+    OS << "  'overlay-relative': '" << (UseOverlayRelative ? "true" : "false")
+       << "',\n";
+  }
+  if (IgnoreNonExistentContents.hasValue())
+    OS << "  'ignore-non-existent-contents': '"
+       << (IgnoreNonExistentContents.getValue() ? "true" : "false") << "',\n";
+  OS << "  'roots': [\n";
+
+  if (!Entries.empty()) {
+    const YAMLVFSEntry &Entry = Entries.front();
+    startDirectory(path::parent_path(Entry.VPath));
+
+    StringRef RPath = Entry.RPath;
+    if (UseOverlayRelative) {
+      unsigned OverlayDirLen = OverlayDir.size();
+      assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
+             "Overlay dir must be contained in RPath");
+      RPath = RPath.slice(OverlayDirLen, RPath.size());
+    }
+
+    writeEntry(path::filename(Entry.VPath), RPath);
+
+    for (const auto &Entry : Entries.slice(1)) {
+      StringRef Dir = path::parent_path(Entry.VPath);
+      if (Dir == DirStack.back())
+        OS << ",\n";
+      else {
+        while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
+          OS << "\n";
+          endDirectory();
+        }
+        OS << ",\n";
+        startDirectory(Dir);
+      }
+      StringRef RPath = Entry.RPath;
+      if (UseOverlayRelative) {
+        unsigned OverlayDirLen = OverlayDir.size();
+        assert(RPath.substr(0, OverlayDirLen) == OverlayDir &&
+               "Overlay dir must be contained in RPath");
+        RPath = RPath.slice(OverlayDirLen, RPath.size());
+      }
+      writeEntry(path::filename(Entry.VPath), RPath);
+    }
+
+    while (!DirStack.empty()) {
+      OS << "\n";
+      endDirectory();
+    }
+    OS << "\n";
+  }
+
+  OS << "  ]\n"
+     << "}\n";
+}
+
+void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
+  llvm::sort(Mappings, [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
+    return LHS.VPath < RHS.VPath;
+  });
+
+  JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
+                       IsOverlayRelative, IgnoreNonExistentContents,
+                       OverlayDir);
+}
+
+VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(
+    const Twine &_Path, RedirectingDirectoryEntry::iterator Begin,
+    RedirectingDirectoryEntry::iterator End, std::error_code &EC)
+    : Dir(_Path.str()), Current(Begin), End(End) {
+  EC = incrementImpl();
+}
+
+std::error_code VFSFromYamlDirIterImpl::increment() {
+  assert(Current != End && "cannot iterate past end");
+  ++Current;
+  return incrementImpl();
+}
+
+std::error_code VFSFromYamlDirIterImpl::incrementImpl() {
+  while (Current != End) {
+    SmallString<128> PathStr(Dir);
+    llvm::sys::path::append(PathStr, (*Current)->getName());
+    sys::fs::file_type Type;
+    switch ((*Current)->getKind()) {
+    case EK_Directory:
+      Type = sys::fs::file_type::directory_file;
+      break;
+    case EK_File:
+      Type = sys::fs::file_type::regular_file;
+      break;
+    }
+    CurrentEntry = directory_entry(PathStr.str(), Type);
+    break;
+  }
+
+  if (Current == End)
+    CurrentEntry = directory_entry();
+  return {};
+}
+
+vfs::recursive_directory_iterator::recursive_directory_iterator(
+    FileSystem &FS_, const Twine &Path, std::error_code &EC)
+    : FS(&FS_) {
+  directory_iterator I = FS->dir_begin(Path, EC);
+  if (I != directory_iterator()) {
+    State = std::make_shared<IterState>();
+    State->push(I);
+  }
+}
+
+vfs::recursive_directory_iterator &
+recursive_directory_iterator::increment(std::error_code &EC) {
+  assert(FS && State && !State->empty() && "incrementing past end");
+  assert(!State->top()->path().empty() && "non-canonical end iterator");
+  vfs::directory_iterator End;
+  if (State->top()->type() == sys::fs::file_type::directory_file) {
+    vfs::directory_iterator I = FS->dir_begin(State->top()->path(), EC);
+    if (I != End) {
+      State->push(I);
+      return *this;
+    }
+  }
+
+  while (!State->empty() && State->top().increment(EC) == End)
+    State->pop();
+
+  if (State->empty())
+    State.reset(); // end iterator
+
+  return *this;
+}
diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt
index 2353e15..f9c877f 100644
--- a/unittests/Support/CMakeLists.txt
+++ b/unittests/Support/CMakeLists.txt
@@ -68,6 +68,7 @@
   TrigramIndexTest.cpp
   UnicodeTest.cpp
   VersionTupleTest.cpp
+  VirtualFileSystemTest.cpp
   YAMLIOTest.cpp
   YAMLParserTest.cpp
   formatted_raw_ostream_test.cpp
diff --git a/unittests/Support/VirtualFileSystemTest.cpp b/unittests/Support/VirtualFileSystemTest.cpp
new file mode 100644
index 0000000..58d9285
--- /dev/null
+++ b/unittests/Support/VirtualFileSystemTest.cpp
@@ -0,0 +1,1601 @@
+//===- unittests/Support/VirtualFileSystem.cpp -------------- VFS tests ---===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <map>
+#include <string>
+
+using namespace llvm;
+using llvm::sys::fs::UniqueID;
+using testing::ElementsAre;
+using testing::Pair;
+using testing::UnorderedElementsAre;
+
+namespace {
+struct DummyFile : public vfs::File {
+  vfs::Status S;
+  explicit DummyFile(vfs::Status S) : S(S) {}
+  llvm::ErrorOr<vfs::Status> status() override { return S; }
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+  getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
+            bool IsVolatile) override {
+    llvm_unreachable("unimplemented");
+  }
+  std::error_code close() override { return std::error_code(); }
+};
+
+class DummyFileSystem : public vfs::FileSystem {
+  int FSID;   // used to produce UniqueIDs
+  int FileID; // used to produce UniqueIDs
+  std::map<std::string, vfs::Status> FilesAndDirs;
+
+  static int getNextFSID() {
+    static int Count = 0;
+    return Count++;
+  }
+
+public:
+  DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
+
+  ErrorOr<vfs::Status> status(const Twine &Path) override {
+    std::map<std::string, vfs::Status>::iterator I =
+        FilesAndDirs.find(Path.str());
+    if (I == FilesAndDirs.end())
+      return make_error_code(llvm::errc::no_such_file_or_directory);
+    return I->second;
+  }
+  ErrorOr<std::unique_ptr<vfs::File>>
+  openFileForRead(const Twine &Path) override {
+    auto S = status(Path);
+    if (S)
+      return std::unique_ptr<vfs::File>(new DummyFile{*S});
+    return S.getError();
+  }
+  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+    return std::string();
+  }
+  std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
+    return std::error_code();
+  }
+  // Map any symlink to "/symlink".
+  std::error_code getRealPath(const Twine &Path,
+                              SmallVectorImpl<char> &Output) const override {
+    auto I = FilesAndDirs.find(Path.str());
+    if (I == FilesAndDirs.end())
+      return make_error_code(llvm::errc::no_such_file_or_directory);
+    if (I->second.isSymlink()) {
+      Output.clear();
+      Twine("/symlink").toVector(Output);
+      return std::error_code();
+    }
+    Output.clear();
+    Path.toVector(Output);
+    return std::error_code();
+  }
+
+  struct DirIterImpl : public llvm::vfs::detail::DirIterImpl {
+    std::map<std::string, vfs::Status> &FilesAndDirs;
+    std::map<std::string, vfs::Status>::iterator I;
+    std::string Path;
+    bool isInPath(StringRef S) {
+      if (Path.size() < S.size() && S.find(Path) == 0) {
+        auto LastSep = S.find_last_of('/');
+        if (LastSep == Path.size() || LastSep == Path.size() - 1)
+          return true;
+      }
+      return false;
+    }
+    DirIterImpl(std::map<std::string, vfs::Status> &FilesAndDirs,
+                const Twine &_Path)
+        : FilesAndDirs(FilesAndDirs), I(FilesAndDirs.begin()),
+          Path(_Path.str()) {
+      for (; I != FilesAndDirs.end(); ++I) {
+        if (isInPath(I->first)) {
+          CurrentEntry =
+              vfs::directory_entry(I->second.getName(), I->second.getType());
+          break;
+        }
+      }
+    }
+    std::error_code increment() override {
+      ++I;
+      for (; I != FilesAndDirs.end(); ++I) {
+        if (isInPath(I->first)) {
+          CurrentEntry =
+              vfs::directory_entry(I->second.getName(), I->second.getType());
+          break;
+        }
+      }
+      if (I == FilesAndDirs.end())
+        CurrentEntry = vfs::directory_entry();
+      return std::error_code();
+    }
+  };
+
+  vfs::directory_iterator dir_begin(const Twine &Dir,
+                                    std::error_code &EC) override {
+    return vfs::directory_iterator(
+        std::make_shared<DirIterImpl>(FilesAndDirs, Dir));
+  }
+
+  void addEntry(StringRef Path, const vfs::Status &Status) {
+    FilesAndDirs[Path] = Status;
+  }
+
+  void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
+    vfs::Status S(Path, UniqueID(FSID, FileID++),
+                  std::chrono::system_clock::now(), 0, 0, 1024,
+                  sys::fs::file_type::regular_file, Perms);
+    addEntry(Path, S);
+  }
+
+  void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
+    vfs::Status S(Path, UniqueID(FSID, FileID++),
+                  std::chrono::system_clock::now(), 0, 0, 0,
+                  sys::fs::file_type::directory_file, Perms);
+    addEntry(Path, S);
+  }
+
+  void addSymlink(StringRef Path) {
+    vfs::Status S(Path, UniqueID(FSID, FileID++),
+                  std::chrono::system_clock::now(), 0, 0, 0,
+                  sys::fs::file_type::symlink_file, sys::fs::all_all);
+    addEntry(Path, S);
+  }
+};
+
+/// Replace back-slashes by front-slashes.
+std::string getPosixPath(std::string S) {
+  SmallString<128> Result;
+  llvm::sys::path::native(S, Result, llvm::sys::path::Style::posix);
+  return Result.str();
+}
+} // end anonymous namespace
+
+TEST(VirtualFileSystemTest, StatusQueries) {
+  IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
+  ErrorOr<vfs::Status> Status((std::error_code()));
+
+  D->addRegularFile("/foo");
+  Status = D->status("/foo");
+  ASSERT_FALSE(Status.getError());
+  EXPECT_TRUE(Status->isStatusKnown());
+  EXPECT_FALSE(Status->isDirectory());
+  EXPECT_TRUE(Status->isRegularFile());
+  EXPECT_FALSE(Status->isSymlink());
+  EXPECT_FALSE(Status->isOther());
+  EXPECT_TRUE(Status->exists());
+
+  D->addDirectory("/bar");
+  Status = D->status("/bar");
+  ASSERT_FALSE(Status.getError());
+  EXPECT_TRUE(Status->isStatusKnown());
+  EXPECT_TRUE(Status->isDirectory());
+  EXPECT_FALSE(Status->isRegularFile());
+  EXPECT_FALSE(Status->isSymlink());
+  EXPECT_FALSE(Status->isOther());
+  EXPECT_TRUE(Status->exists());
+
+  D->addSymlink("/baz");
+  Status = D->status("/baz");
+  ASSERT_FALSE(Status.getError());
+  EXPECT_TRUE(Status->isStatusKnown());
+  EXPECT_FALSE(Status->isDirectory());
+  EXPECT_FALSE(Status->isRegularFile());
+  EXPECT_TRUE(Status->isSymlink());
+  EXPECT_FALSE(Status->isOther());
+  EXPECT_TRUE(Status->exists());
+
+  EXPECT_TRUE(Status->equivalent(*Status));
+  ErrorOr<vfs::Status> Status2 = D->status("/foo");
+  ASSERT_FALSE(Status2.getError());
+  EXPECT_FALSE(Status->equivalent(*Status2));
+}
+
+TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
+  IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
+  ErrorOr<vfs::Status> Status((std::error_code()));
+  EXPECT_FALSE(Status = D->status("/foo"));
+
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(new vfs::OverlayFileSystem(D));
+  EXPECT_FALSE(Status = O->status("/foo"));
+
+  D->addRegularFile("/foo");
+  Status = D->status("/foo");
+  EXPECT_FALSE(Status.getError());
+
+  ErrorOr<vfs::Status> Status2((std::error_code()));
+  Status2 = O->status("/foo");
+  EXPECT_FALSE(Status2.getError());
+  EXPECT_TRUE(Status->equivalent(*Status2));
+}
+
+TEST(VirtualFileSystemTest, GetRealPathInOverlay) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addRegularFile("/foo");
+  Lower->addSymlink("/lower_link");
+  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
+
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(Upper);
+
+  // Regular file.
+  SmallString<16> RealPath;
+  EXPECT_FALSE(O->getRealPath("/foo", RealPath));
+  EXPECT_EQ(RealPath.str(), "/foo");
+
+  // Expect no error getting real path for symlink in lower overlay.
+  EXPECT_FALSE(O->getRealPath("/lower_link", RealPath));
+  EXPECT_EQ(RealPath.str(), "/symlink");
+
+  // Try a non-existing link.
+  EXPECT_EQ(O->getRealPath("/upper_link", RealPath),
+            errc::no_such_file_or_directory);
+
+  // Add a new symlink in upper.
+  Upper->addSymlink("/upper_link");
+  EXPECT_FALSE(O->getRealPath("/upper_link", RealPath));
+  EXPECT_EQ(RealPath.str(), "/symlink");
+}
+
+TEST(VirtualFileSystemTest, OverlayFiles) {
+  IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Top(new DummyFileSystem());
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Base));
+  O->pushOverlay(Middle);
+  O->pushOverlay(Top);
+
+  ErrorOr<vfs::Status> Status1((std::error_code())),
+      Status2((std::error_code())), Status3((std::error_code())),
+      StatusB((std::error_code())), StatusM((std::error_code())),
+      StatusT((std::error_code()));
+
+  Base->addRegularFile("/foo");
+  StatusB = Base->status("/foo");
+  ASSERT_FALSE(StatusB.getError());
+  Status1 = O->status("/foo");
+  ASSERT_FALSE(Status1.getError());
+  Middle->addRegularFile("/foo");
+  StatusM = Middle->status("/foo");
+  ASSERT_FALSE(StatusM.getError());
+  Status2 = O->status("/foo");
+  ASSERT_FALSE(Status2.getError());
+  Top->addRegularFile("/foo");
+  StatusT = Top->status("/foo");
+  ASSERT_FALSE(StatusT.getError());
+  Status3 = O->status("/foo");
+  ASSERT_FALSE(Status3.getError());
+
+  EXPECT_TRUE(Status1->equivalent(*StatusB));
+  EXPECT_TRUE(Status2->equivalent(*StatusM));
+  EXPECT_TRUE(Status3->equivalent(*StatusT));
+
+  EXPECT_FALSE(Status1->equivalent(*Status2));
+  EXPECT_FALSE(Status2->equivalent(*Status3));
+  EXPECT_FALSE(Status1->equivalent(*Status3));
+}
+
+TEST(VirtualFileSystemTest, OverlayDirsNonMerged) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(Upper);
+
+  Lower->addDirectory("/lower-only");
+  Upper->addDirectory("/upper-only");
+
+  // non-merged paths should be the same
+  ErrorOr<vfs::Status> Status1 = Lower->status("/lower-only");
+  ASSERT_FALSE(Status1.getError());
+  ErrorOr<vfs::Status> Status2 = O->status("/lower-only");
+  ASSERT_FALSE(Status2.getError());
+  EXPECT_TRUE(Status1->equivalent(*Status2));
+
+  Status1 = Upper->status("/upper-only");
+  ASSERT_FALSE(Status1.getError());
+  Status2 = O->status("/upper-only");
+  ASSERT_FALSE(Status2.getError());
+  EXPECT_TRUE(Status1->equivalent(*Status2));
+}
+
+TEST(VirtualFileSystemTest, MergedDirPermissions) {
+  // merged directories get the permissions of the upper dir
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(Upper);
+
+  ErrorOr<vfs::Status> Status((std::error_code()));
+  Lower->addDirectory("/both", sys::fs::owner_read);
+  Upper->addDirectory("/both", sys::fs::owner_all | sys::fs::group_read);
+  Status = O->status("/both");
+  ASSERT_FALSE(Status.getError());
+  EXPECT_EQ(0740, Status->getPermissions());
+
+  // permissions (as usual) are not recursively applied
+  Lower->addRegularFile("/both/foo", sys::fs::owner_read);
+  Upper->addRegularFile("/both/bar", sys::fs::owner_write);
+  Status = O->status("/both/foo");
+  ASSERT_FALSE(Status.getError());
+  EXPECT_EQ(0400, Status->getPermissions());
+  Status = O->status("/both/bar");
+  ASSERT_FALSE(Status.getError());
+  EXPECT_EQ(0200, Status->getPermissions());
+}
+
+namespace {
+struct ScopedDir {
+  SmallString<128> Path;
+  ScopedDir(const Twine &Name, bool Unique = false) {
+    std::error_code EC;
+    if (Unique) {
+      EC = llvm::sys::fs::createUniqueDirectory(Name, Path);
+    } else {
+      Path = Name.str();
+      EC = llvm::sys::fs::create_directory(Twine(Path));
+    }
+    if (EC)
+      Path = "";
+    EXPECT_FALSE(EC);
+  }
+  ~ScopedDir() {
+    if (Path != "") {
+      EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
+    }
+  }
+  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) {
+  ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
+
+  std::error_code EC;
+  vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC);
+  ASSERT_FALSE(EC);
+  EXPECT_EQ(vfs::directory_iterator(), I); // empty directory is empty
+
+  ScopedDir _a(TestDirectory + "/a");
+  ScopedDir _ab(TestDirectory + "/a/b");
+  ScopedDir _c(TestDirectory + "/c");
+  ScopedDir _cd(TestDirectory + "/c/d");
+
+  I = FS->dir_begin(Twine(TestDirectory), EC);
+  ASSERT_FALSE(EC);
+  ASSERT_NE(vfs::directory_iterator(), I);
+  // Check either a or c, since we can't rely on the iteration order.
+  EXPECT_TRUE(I->path().endswith("a") || I->path().endswith("c"));
+  I.increment(EC);
+  ASSERT_FALSE(EC);
+  ASSERT_NE(vfs::directory_iterator(), I);
+  EXPECT_TRUE(I->path().endswith("a") || I->path().endswith("c"));
+  I.increment(EC);
+  EXPECT_EQ(vfs::directory_iterator(), I);
+}
+
+#ifdef LLVM_ON_UNIX
+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");
+
+  // Should get no iteration error, but a stat error for the broken symlinks.
+  std::map<std::string, std::error_code> StatResults;
+  std::error_code EC;
+  for (vfs::directory_iterator I = FS->dir_begin(Twine(TestDirectory), EC), E;
+       I != E; I.increment(EC)) {
+    EXPECT_FALSE(EC);
+    StatResults[sys::path::filename(I->path())] =
+        FS->status(I->path()).getError();
+  }
+  EXPECT_THAT(
+      StatResults,
+      ElementsAre(
+          Pair("a", std::make_error_code(std::errc::no_such_file_or_directory)),
+          Pair("b", std::error_code()),
+          Pair("c",
+               std::make_error_code(std::errc::no_such_file_or_directory))));
+}
+#endif
+
+TEST(VirtualFileSystemTest, BasicRealFSRecursiveIteration) {
+  ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem();
+
+  std::error_code EC;
+  auto I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
+  ASSERT_FALSE(EC);
+  EXPECT_EQ(vfs::recursive_directory_iterator(), I); // empty directory is empty
+
+  ScopedDir _a(TestDirectory + "/a");
+  ScopedDir _ab(TestDirectory + "/a/b");
+  ScopedDir _c(TestDirectory + "/c");
+  ScopedDir _cd(TestDirectory + "/c/d");
+
+  I = vfs::recursive_directory_iterator(*FS, Twine(TestDirectory), EC);
+  ASSERT_FALSE(EC);
+  ASSERT_NE(vfs::recursive_directory_iterator(), I);
+
+  std::vector<std::string> Contents;
+  for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
+       I.increment(EC)) {
+    Contents.push_back(I->path());
+  }
+
+  // Check contents, which may be in any order
+  EXPECT_EQ(4U, Contents.size());
+  int Counts[4] = {0, 0, 0, 0};
+  for (const std::string &Name : Contents) {
+    ASSERT_FALSE(Name.empty());
+    int Index = Name[Name.size() - 1] - 'a';
+    ASSERT_TRUE(Index >= 0 && Index < 4);
+    Counts[Index]++;
+  }
+  EXPECT_EQ(1, Counts[0]); // a
+  EXPECT_EQ(1, Counts[1]); // b
+  EXPECT_EQ(1, Counts[2]); // c
+  EXPECT_EQ(1, Counts[3]); // d
+}
+
+#ifdef LLVM_ON_UNIX
+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> VisitedBrokenSymlinks;
+  std::vector<std::string> VisitedNonBrokenSymlinks;
+  std::error_code EC;
+  for (vfs::recursive_directory_iterator I(*FS, Twine(TestDirectory), EC), E;
+       I != E; I.increment(EC)) {
+    EXPECT_FALSE(EC);
+    (FS->status(I->path()) ? VisitedNonBrokenSymlinks : VisitedBrokenSymlinks)
+        .push_back(I->path());
+  }
+
+  // Check visited file names.
+  EXPECT_THAT(VisitedBrokenSymlinks,
+              UnorderedElementsAre(StringRef(_a), StringRef(_ba),
+                                   StringRef(_bc), StringRef(_c),
+                                   StringRef(_e)));
+  EXPECT_THAT(VisitedNonBrokenSymlinks,
+              UnorderedElementsAre(StringRef(_b), StringRef(_bb), StringRef(_d),
+                                   StringRef(_dd), StringRef(_ddd)));
+}
+#endif
+
+template <typename DirIter>
+static void checkContents(DirIter I, ArrayRef<StringRef> ExpectedOut) {
+  std::error_code EC;
+  SmallVector<StringRef, 4> Expected(ExpectedOut.begin(), ExpectedOut.end());
+  SmallVector<std::string, 4> InputToCheck;
+
+  // Do not rely on iteration order to check for contents, sort both
+  // content vectors before comparison.
+  for (DirIter E; !EC && I != E; I.increment(EC))
+    InputToCheck.push_back(I->path());
+
+  llvm::sort(InputToCheck);
+  llvm::sort(Expected);
+  EXPECT_EQ(InputToCheck.size(), Expected.size());
+
+  unsigned LastElt = std::min(InputToCheck.size(), Expected.size());
+  for (unsigned Idx = 0; Idx != LastElt; ++Idx)
+    EXPECT_EQ(StringRef(InputToCheck[Idx]), Expected[Idx]);
+}
+
+TEST(VirtualFileSystemTest, OverlayIteration) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(Upper);
+
+  std::error_code EC;
+  checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
+
+  Lower->addRegularFile("/file1");
+  checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file1"));
+
+  Upper->addRegularFile("/file2");
+  checkContents(O->dir_begin("/", EC), {"/file2", "/file1"});
+
+  Lower->addDirectory("/dir1");
+  Lower->addRegularFile("/dir1/foo");
+  Upper->addDirectory("/dir2");
+  Upper->addRegularFile("/dir2/foo");
+  checkContents(O->dir_begin("/dir2", EC), ArrayRef<StringRef>("/dir2/foo"));
+  checkContents(O->dir_begin("/", EC), {"/dir2", "/file2", "/dir1", "/file1"});
+}
+
+TEST(VirtualFileSystemTest, OverlayRecursiveIteration) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(Middle);
+  O->pushOverlay(Upper);
+
+  std::error_code EC;
+  checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
+                ArrayRef<StringRef>());
+
+  Lower->addRegularFile("/file1");
+  checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
+                ArrayRef<StringRef>("/file1"));
+
+  Upper->addDirectory("/dir");
+  Upper->addRegularFile("/dir/file2");
+  checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
+                {"/dir", "/dir/file2", "/file1"});
+
+  Lower->addDirectory("/dir1");
+  Lower->addRegularFile("/dir1/foo");
+  Lower->addDirectory("/dir1/a");
+  Lower->addRegularFile("/dir1/a/b");
+  Middle->addDirectory("/a");
+  Middle->addDirectory("/a/b");
+  Middle->addDirectory("/a/b/c");
+  Middle->addRegularFile("/a/b/c/d");
+  Middle->addRegularFile("/hiddenByUp");
+  Upper->addDirectory("/dir2");
+  Upper->addRegularFile("/dir2/foo");
+  Upper->addRegularFile("/hiddenByUp");
+  checkContents(vfs::recursive_directory_iterator(*O, "/dir2", EC),
+                ArrayRef<StringRef>("/dir2/foo"));
+  checkContents(vfs::recursive_directory_iterator(*O, "/", EC),
+                {"/dir", "/dir/file2", "/dir2", "/dir2/foo", "/hiddenByUp",
+                 "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/dir1", "/dir1/a",
+                 "/dir1/a/b", "/dir1/foo", "/file1"});
+}
+
+TEST(VirtualFileSystemTest, ThreeLevelIteration) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(Middle);
+  O->pushOverlay(Upper);
+
+  std::error_code EC;
+  checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>());
+
+  Middle->addRegularFile("/file2");
+  checkContents(O->dir_begin("/", EC), ArrayRef<StringRef>("/file2"));
+
+  Lower->addRegularFile("/file1");
+  Upper->addRegularFile("/file3");
+  checkContents(O->dir_begin("/", EC), {"/file3", "/file2", "/file1"});
+}
+
+TEST(VirtualFileSystemTest, HiddenInIteration) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());
+  IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(Middle);
+  O->pushOverlay(Upper);
+
+  std::error_code EC;
+  Lower->addRegularFile("/onlyInLow");
+  Lower->addDirectory("/hiddenByMid");
+  Lower->addDirectory("/hiddenByUp");
+  Middle->addRegularFile("/onlyInMid");
+  Middle->addRegularFile("/hiddenByMid");
+  Middle->addDirectory("/hiddenByUp");
+  Upper->addRegularFile("/onlyInUp");
+  Upper->addRegularFile("/hiddenByUp");
+  checkContents(
+      O->dir_begin("/", EC),
+      {"/hiddenByUp", "/onlyInUp", "/hiddenByMid", "/onlyInMid", "/onlyInLow"});
+
+  // Make sure we get the top-most entry
+  {
+    std::error_code EC;
+    vfs::directory_iterator I = O->dir_begin("/", EC), E;
+    for (; !EC && I != E; I.increment(EC))
+      if (I->path() == "/hiddenByUp")
+        break;
+    ASSERT_NE(E, I);
+    EXPECT_EQ(sys::fs::file_type::regular_file, I->type());
+  }
+  {
+    std::error_code EC;
+    vfs::directory_iterator I = O->dir_begin("/", EC), E;
+    for (; !EC && I != E; I.increment(EC))
+      if (I->path() == "/hiddenByMid")
+        break;
+    ASSERT_NE(E, I);
+    EXPECT_EQ(sys::fs::file_type::regular_file, I->type());
+  }
+}
+
+class InMemoryFileSystemTest : public ::testing::Test {
+protected:
+  llvm::vfs::InMemoryFileSystem FS;
+  llvm::vfs::InMemoryFileSystem NormalizedFS;
+
+  InMemoryFileSystemTest()
+      : FS(/*UseNormalizedPaths=*/false),
+        NormalizedFS(/*UseNormalizedPaths=*/true) {}
+};
+
+MATCHER_P2(IsHardLinkTo, FS, Target, "") {
+  StringRef From = arg;
+  StringRef To = Target;
+  auto OpenedFrom = FS->openFileForRead(From);
+  auto OpenedTo = FS->openFileForRead(To);
+  return !OpenedFrom.getError() && !OpenedTo.getError() &&
+         (*OpenedFrom)->status()->getUniqueID() ==
+             (*OpenedTo)->status()->getUniqueID();
+}
+
+TEST_F(InMemoryFileSystemTest, IsEmpty) {
+  auto Stat = FS.status("/a");
+  ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString();
+  Stat = FS.status("/");
+  ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString();
+}
+
+TEST_F(InMemoryFileSystemTest, WindowsPath) {
+  FS.addFile("c:/windows/system128/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
+  auto Stat = FS.status("c:");
+#if !defined(_WIN32)
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
+#endif
+  Stat = FS.status("c:/windows/system128/foo.cpp");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
+  FS.addFile("d:/windows/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
+  Stat = FS.status("d:/windows/foo.cpp");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
+}
+
+TEST_F(InMemoryFileSystemTest, OverlayFile) {
+  FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
+  NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
+  auto Stat = FS.status("/");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
+  Stat = FS.status("/.");
+  ASSERT_FALSE(Stat);
+  Stat = NormalizedFS.status("/.");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
+  Stat = FS.status("/a");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_EQ("/a", Stat->getName());
+}
+
+TEST_F(InMemoryFileSystemTest, OverlayFileNoOwn) {
+  auto Buf = MemoryBuffer::getMemBuffer("a");
+  FS.addFileNoOwn("/a", 0, Buf.get());
+  auto Stat = FS.status("/a");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_EQ("/a", Stat->getName());
+}
+
+TEST_F(InMemoryFileSystemTest, OpenFileForRead) {
+  FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
+  FS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
+  FS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
+  NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
+  NormalizedFS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
+  NormalizedFS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
+  auto File = FS.openFileForRead("/a");
+  ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
+  File = FS.openFileForRead("/a"); // Open again.
+  ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
+  File = NormalizedFS.openFileForRead("/././a"); // Open again.
+  ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
+  File = FS.openFileForRead("/");
+  ASSERT_EQ(File.getError(), errc::invalid_argument) << FS.toString();
+  File = FS.openFileForRead("/b");
+  ASSERT_EQ(File.getError(), errc::no_such_file_or_directory) << FS.toString();
+  File = FS.openFileForRead("./c");
+  ASSERT_FALSE(File);
+  File = FS.openFileForRead("e/../d");
+  ASSERT_FALSE(File);
+  File = NormalizedFS.openFileForRead("./c");
+  ASSERT_EQ("c", (*(*File)->getBuffer("ignored"))->getBuffer());
+  File = NormalizedFS.openFileForRead("e/../d");
+  ASSERT_EQ("d", (*(*File)->getBuffer("ignored"))->getBuffer());
+}
+
+TEST_F(InMemoryFileSystemTest, DuplicatedFile) {
+  ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
+  ASSERT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("a")));
+  ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
+  ASSERT_FALSE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("b")));
+}
+
+TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
+  FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""));
+  FS.addFile("/b/c", 0, MemoryBuffer::getMemBuffer(""));
+
+  std::error_code EC;
+  vfs::directory_iterator I = FS.dir_begin("/", EC);
+  ASSERT_FALSE(EC);
+  ASSERT_EQ("/a", I->path());
+  I.increment(EC);
+  ASSERT_FALSE(EC);
+  ASSERT_EQ("/b", I->path());
+  I.increment(EC);
+  ASSERT_FALSE(EC);
+  ASSERT_EQ(vfs::directory_iterator(), I);
+
+  I = FS.dir_begin("/b", EC);
+  ASSERT_FALSE(EC);
+  // When on Windows, we end up with "/b\\c" as the name.  Convert to Posix
+  // path for the sake of the comparison.
+  ASSERT_EQ("/b/c", getPosixPath(I->path()));
+  I.increment(EC);
+  ASSERT_FALSE(EC);
+  ASSERT_EQ(vfs::directory_iterator(), I);
+}
+
+TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
+  FS.setCurrentWorkingDirectory("/b");
+  FS.addFile("c", 0, MemoryBuffer::getMemBuffer(""));
+
+  auto Stat = FS.status("/b/c");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_EQ("/b/c", Stat->getName());
+  ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory());
+
+  Stat = FS.status("c");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+
+  NormalizedFS.setCurrentWorkingDirectory("/b/c");
+  NormalizedFS.setCurrentWorkingDirectory(".");
+  ASSERT_EQ("/b/c",
+            getPosixPath(NormalizedFS.getCurrentWorkingDirectory().get()));
+  NormalizedFS.setCurrentWorkingDirectory("..");
+  ASSERT_EQ("/b",
+            getPosixPath(NormalizedFS.getCurrentWorkingDirectory().get()));
+}
+
+#if !defined(_WIN32)
+TEST_F(InMemoryFileSystemTest, GetRealPath) {
+  SmallString<16> Path;
+  EXPECT_EQ(FS.getRealPath("b", Path), errc::operation_not_permitted);
+
+  auto GetRealPath = [this](StringRef P) {
+    SmallString<16> Output;
+    auto EC = FS.getRealPath(P, Output);
+    EXPECT_FALSE(EC);
+    return Output.str().str();
+  };
+
+  FS.setCurrentWorkingDirectory("a");
+  EXPECT_EQ(GetRealPath("b"), "a/b");
+  EXPECT_EQ(GetRealPath("../b"), "b");
+  EXPECT_EQ(GetRealPath("b/./c"), "a/b/c");
+
+  FS.setCurrentWorkingDirectory("/a");
+  EXPECT_EQ(GetRealPath("b"), "/a/b");
+  EXPECT_EQ(GetRealPath("../b"), "/b");
+  EXPECT_EQ(GetRealPath("b/./c"), "/a/b/c");
+}
+#endif // _WIN32
+
+TEST_F(InMemoryFileSystemTest, AddFileWithUser) {
+  FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), 0xFEEDFACE);
+  auto Stat = FS.status("/a");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isDirectory());
+  ASSERT_EQ(0xFEEDFACE, Stat->getUser());
+  Stat = FS.status("/a/b");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isDirectory());
+  ASSERT_EQ(0xFEEDFACE, Stat->getUser());
+  Stat = FS.status("/a/b/c");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isRegularFile());
+  ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions());
+  ASSERT_EQ(0xFEEDFACE, Stat->getUser());
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileWithGroup) {
+  FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, 0xDABBAD00);
+  auto Stat = FS.status("/a");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isDirectory());
+  ASSERT_EQ(0xDABBAD00, Stat->getGroup());
+  Stat = FS.status("/a/b");
+  ASSERT_TRUE(Stat->isDirectory());
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_EQ(0xDABBAD00, Stat->getGroup());
+  Stat = FS.status("/a/b/c");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isRegularFile());
+  ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions());
+  ASSERT_EQ(0xDABBAD00, Stat->getGroup());
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileWithFileType) {
+  FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, None,
+             sys::fs::file_type::socket_file);
+  auto Stat = FS.status("/a");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isDirectory());
+  Stat = FS.status("/a/b");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isDirectory());
+  Stat = FS.status("/a/b/c");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_EQ(sys::fs::file_type::socket_file, Stat->getType());
+  ASSERT_EQ(sys::fs::perms::all_all, Stat->getPermissions());
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileWithPerms) {
+  FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), None, None, None,
+             sys::fs::perms::owner_read | sys::fs::perms::owner_write);
+  auto Stat = FS.status("/a");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isDirectory());
+  ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write |
+                sys::fs::perms::owner_exe,
+            Stat->getPermissions());
+  Stat = FS.status("/a/b");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isDirectory());
+  ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write |
+                sys::fs::perms::owner_exe,
+            Stat->getPermissions());
+  Stat = FS.status("/a/b/c");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isRegularFile());
+  ASSERT_EQ(sys::fs::perms::owner_read | sys::fs::perms::owner_write,
+            Stat->getPermissions());
+}
+
+TEST_F(InMemoryFileSystemTest, AddDirectoryThenAddChild) {
+  FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""), /*User=*/None,
+             /*Group=*/None, sys::fs::file_type::directory_file);
+  FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("abc"), /*User=*/None,
+             /*Group=*/None, sys::fs::file_type::regular_file);
+  auto Stat = FS.status("/a");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isDirectory());
+  Stat = FS.status("/a/b");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+  ASSERT_TRUE(Stat->isRegularFile());
+}
+
+// Test that the name returned by status() is in the same form as the path that
+// was requested (to match the behavior of RealFileSystem).
+TEST_F(InMemoryFileSystemTest, StatusName) {
+  NormalizedFS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"),
+                       /*User=*/None,
+                       /*Group=*/None, sys::fs::file_type::regular_file);
+  NormalizedFS.setCurrentWorkingDirectory("/a/b");
+
+  // Access using InMemoryFileSystem::status.
+  auto Stat = NormalizedFS.status("../b/c");
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n"
+                                << NormalizedFS.toString();
+  ASSERT_TRUE(Stat->isRegularFile());
+  ASSERT_EQ("../b/c", Stat->getName());
+
+  // Access using InMemoryFileAdaptor::status.
+  auto File = NormalizedFS.openFileForRead("../b/c");
+  ASSERT_FALSE(File.getError()) << File.getError() << "\n"
+                                << NormalizedFS.toString();
+  Stat = (*File)->status();
+  ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n"
+                                << NormalizedFS.toString();
+  ASSERT_TRUE(Stat->isRegularFile());
+  ASSERT_EQ("../b/c", Stat->getName());
+
+  // Access using a directory iterator.
+  std::error_code EC;
+  llvm::vfs::directory_iterator It = NormalizedFS.dir_begin("../b", EC);
+  // When on Windows, we end up with "../b\\c" as the name.  Convert to Posix
+  // path for the sake of the comparison.
+  ASSERT_EQ("../b/c", getPosixPath(It->path()));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) {
+  StringRef FromLink = "/path/to/FROM/link";
+  StringRef Target = "/path/to/TO/file";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
+  EXPECT_TRUE(FS.addHardLink(FromLink, Target));
+  EXPECT_THAT(FromLink, IsHardLinkTo(&FS, Target));
+  EXPECT_TRUE(FS.status(FromLink)->getSize() == FS.status(Target)->getSize());
+  EXPECT_TRUE(FS.getBufferForFile(FromLink)->get()->getBuffer() ==
+              FS.getBufferForFile(Target)->get()->getBuffer());
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) {
+  StringRef Link0 = "/path/to/0/link";
+  StringRef Link1 = "/path/to/1/link";
+  StringRef Link2 = "/path/to/2/link";
+  StringRef Target = "/path/to/target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target file"));
+  EXPECT_TRUE(FS.addHardLink(Link2, Target));
+  EXPECT_TRUE(FS.addHardLink(Link1, Link2));
+  EXPECT_TRUE(FS.addHardLink(Link0, Link1));
+  EXPECT_THAT(Link0, IsHardLinkTo(&FS, Target));
+  EXPECT_THAT(Link1, IsHardLinkTo(&FS, Target));
+  EXPECT_THAT(Link2, IsHardLinkTo(&FS, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) {
+  EXPECT_FALSE(FS.addHardLink("/path/to/link", "/path/to/target"));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
+  FS.addFile(Link, 0, MemoryBuffer::getMemBuffer("content of link"));
+  EXPECT_FALSE(FS.addHardLink(Link, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
+  EXPECT_TRUE(FS.addHardLink(Link, Target));
+  EXPECT_FALSE(FS.addHardLink(Link, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  StringRef Content = "content of target";
+  EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_TRUE(FS.addHardLink(Link, Target));
+  EXPECT_TRUE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(Content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  StringRef Content = "content of target";
+  StringRef LinkContent = "different content of link";
+  EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_TRUE(FS.addHardLink(Link, Target));
+  EXPECT_FALSE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(LinkContent)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) {
+  StringRef Dir = "path/to/dummy/dir";
+  StringRef Link = "/path/to/link";
+  StringRef File = "path/to/dummy/dir/target";
+  StringRef Content = "content of target";
+  EXPECT_TRUE(FS.addFile(File, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_FALSE(FS.addHardLink(Link, Dir));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromADirectory) {
+  StringRef Dir = "path/to/dummy/dir";
+  StringRef Target = "path/to/dummy/dir/target";
+  StringRef Content = "content of target";
+  EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_FALSE(FS.addHardLink(Dir, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkUnderAFile) {
+  StringRef CommonContent = "content string";
+  FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer(CommonContent));
+  FS.addFile("/c/d", 0, MemoryBuffer::getMemBuffer(CommonContent));
+  EXPECT_FALSE(FS.addHardLink("/c/d/e", "/a/b"));
+}
+
+TEST_F(InMemoryFileSystemTest, RecursiveIterationWithHardLink) {
+  std::error_code EC;
+  FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("content string"));
+  EXPECT_TRUE(FS.addHardLink("/c/d", "/a/b"));
+  auto I = vfs::recursive_directory_iterator(FS, "/", EC);
+  ASSERT_FALSE(EC);
+  std::vector<std::string> Nodes;
+  for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
+       I.increment(EC)) {
+    Nodes.push_back(getPosixPath(I->path()));
+  }
+  EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/a", "/a/b", "/c", "/c/d"));
+}
+
+// NOTE: in the tests below, we use '//root/' as our root directory, since it is
+// a legal *absolute* path on Windows as well as *nix.
+class VFSFromYAMLTest : public ::testing::Test {
+public:
+  int NumDiagnostics;
+
+  void SetUp() override { NumDiagnostics = 0; }
+
+  static void CountingDiagHandler(const SMDiagnostic &, void *Context) {
+    VFSFromYAMLTest *Test = static_cast<VFSFromYAMLTest *>(Context);
+    ++Test->NumDiagnostics;
+  }
+
+  IntrusiveRefCntPtr<vfs::FileSystem>
+  getFromYAMLRawString(StringRef Content,
+                       IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS) {
+    std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(Content);
+    return getVFSFromYAML(std::move(Buffer), CountingDiagHandler, "", this,
+                          ExternalFS);
+  }
+
+  IntrusiveRefCntPtr<vfs::FileSystem> getFromYAMLString(
+      StringRef Content,
+      IntrusiveRefCntPtr<vfs::FileSystem> ExternalFS = new DummyFileSystem()) {
+    std::string VersionPlusContent("{\n  'version':0,\n");
+    VersionPlusContent += Content.slice(Content.find('{') + 1, StringRef::npos);
+    return getFromYAMLRawString(VersionPlusContent, ExternalFS);
+  }
+
+  // This is intended as a "XFAIL" for windows hosts.
+  bool supportsSameDirMultipleYAMLEntries() {
+    Triple Host(Triple::normalize(sys::getProcessTriple()));
+    return !Host.isOSWindows();
+  }
+};
+
+TEST_F(VFSFromYAMLTest, BasicVFSFromYAML) {
+  IntrusiveRefCntPtr<vfs::FileSystem> FS;
+  FS = getFromYAMLString("");
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString("[]");
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString("'string'");
+  EXPECT_EQ(nullptr, FS.get());
+  EXPECT_EQ(3, NumDiagnostics);
+}
+
+TEST_F(VFSFromYAMLTest, MappedFiles) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addRegularFile("//root/foo/bar/a");
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+      "{ 'roots': [\n"
+      "{\n"
+      "  'type': 'directory',\n"
+      "  'name': '//root/',\n"
+      "  'contents': [ {\n"
+      "                  'type': 'file',\n"
+      "                  'name': 'file1',\n"
+      "                  'external-contents': '//root/foo/bar/a'\n"
+      "                },\n"
+      "                {\n"
+      "                  'type': 'file',\n"
+      "                  'name': 'file2',\n"
+      "                  'external-contents': '//root/foo/b'\n"
+      "                }\n"
+      "              ]\n"
+      "}\n"
+      "]\n"
+      "}",
+      Lower);
+  ASSERT_TRUE(FS.get() != nullptr);
+
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(FS);
+
+  // file
+  ErrorOr<vfs::Status> S = O->status("//root/file1");
+  ASSERT_FALSE(S.getError());
+  EXPECT_EQ("//root/foo/bar/a", S->getName());
+  EXPECT_TRUE(S->IsVFSMapped);
+
+  ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
+  EXPECT_EQ("//root/foo/bar/a", SLower->getName());
+  EXPECT_TRUE(S->equivalent(*SLower));
+  EXPECT_FALSE(SLower->IsVFSMapped);
+
+  // file after opening
+  auto OpenedF = O->openFileForRead("//root/file1");
+  ASSERT_FALSE(OpenedF.getError());
+  auto OpenedS = (*OpenedF)->status();
+  ASSERT_FALSE(OpenedS.getError());
+  EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
+  EXPECT_TRUE(OpenedS->IsVFSMapped);
+
+  // directory
+  S = O->status("//root/");
+  ASSERT_FALSE(S.getError());
+  EXPECT_TRUE(S->isDirectory());
+  EXPECT_TRUE(S->equivalent(*O->status("//root/"))); // non-volatile UniqueID
+
+  // broken mapping
+  EXPECT_EQ(O->status("//root/file2").getError(),
+            llvm::errc::no_such_file_or_directory);
+  EXPECT_EQ(0, NumDiagnostics);
+}
+
+TEST_F(VFSFromYAMLTest, CaseInsensitive) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addRegularFile("//root/foo/bar/a");
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+      "{ 'case-sensitive': 'false',\n"
+      "  'roots': [\n"
+      "{\n"
+      "  'type': 'directory',\n"
+      "  'name': '//root/',\n"
+      "  'contents': [ {\n"
+      "                  'type': 'file',\n"
+      "                  'name': 'XX',\n"
+      "                  'external-contents': '//root/foo/bar/a'\n"
+      "                }\n"
+      "              ]\n"
+      "}]}",
+      Lower);
+  ASSERT_TRUE(FS.get() != nullptr);
+
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(FS);
+
+  ErrorOr<vfs::Status> S = O->status("//root/XX");
+  ASSERT_FALSE(S.getError());
+
+  ErrorOr<vfs::Status> SS = O->status("//root/xx");
+  ASSERT_FALSE(SS.getError());
+  EXPECT_TRUE(S->equivalent(*SS));
+  SS = O->status("//root/xX");
+  EXPECT_TRUE(S->equivalent(*SS));
+  SS = O->status("//root/Xx");
+  EXPECT_TRUE(S->equivalent(*SS));
+  EXPECT_EQ(0, NumDiagnostics);
+}
+
+TEST_F(VFSFromYAMLTest, CaseSensitive) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addRegularFile("//root/foo/bar/a");
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+      "{ 'case-sensitive': 'true',\n"
+      "  'roots': [\n"
+      "{\n"
+      "  'type': 'directory',\n"
+      "  'name': '//root/',\n"
+      "  'contents': [ {\n"
+      "                  'type': 'file',\n"
+      "                  'name': 'XX',\n"
+      "                  'external-contents': '//root/foo/bar/a'\n"
+      "                }\n"
+      "              ]\n"
+      "}]}",
+      Lower);
+  ASSERT_TRUE(FS.get() != nullptr);
+
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(FS);
+
+  ErrorOr<vfs::Status> SS = O->status("//root/xx");
+  EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
+  SS = O->status("//root/xX");
+  EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
+  SS = O->status("//root/Xx");
+  EXPECT_EQ(SS.getError(), llvm::errc::no_such_file_or_directory);
+  EXPECT_EQ(0, NumDiagnostics);
+}
+
+TEST_F(VFSFromYAMLTest, IllegalVFSFile) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+
+  // invalid YAML at top-level
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString("{]", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  // invalid YAML in roots
+  FS = getFromYAMLString("{ 'roots':[}", Lower);
+  // invalid YAML in directory
+  FS = getFromYAMLString(
+      "{ 'roots':[ { 'name': 'foo', 'type': 'directory', 'contents': [}",
+      Lower);
+  EXPECT_EQ(nullptr, FS.get());
+
+  // invalid configuration
+  FS = getFromYAMLString("{ 'knobular': 'true', 'roots':[] }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString("{ 'case-sensitive': 'maybe', 'roots':[] }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+
+  // invalid roots
+  FS = getFromYAMLString("{ 'roots':'' }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString("{ 'roots':{} }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+
+  // invalid entries
+  FS = getFromYAMLString(
+      "{ 'roots':[ { 'type': 'other', 'name': 'me', 'contents': '' }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': [], "
+                         "'external-contents': 'other' }",
+                         Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString(
+      "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': [] }",
+      Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString(
+      "{ 'roots':[ { 'type': 'file', 'name': 'me', 'external-contents': {} }",
+      Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString(
+      "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': {} }",
+      Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString(
+      "{ 'roots':[ { 'type': 'directory', 'name': 'me', 'contents': '' }",
+      Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString(
+      "{ 'roots':[ { 'thingy': 'directory', 'name': 'me', 'contents': [] }",
+      Lower);
+  EXPECT_EQ(nullptr, FS.get());
+
+  // missing mandatory fields
+  FS = getFromYAMLString("{ 'roots':[ { 'type': 'file', 'name': 'me' }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString(
+      "{ 'roots':[ { 'type': 'file', 'external-contents': 'other' }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString("{ 'roots':[ { 'name': 'me', 'contents': [] }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+
+  // duplicate keys
+  FS = getFromYAMLString("{ 'roots':[], 'roots':[] }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLString(
+      "{ 'case-sensitive':'true', 'case-sensitive':'true', 'roots':[] }",
+      Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS =
+      getFromYAMLString("{ 'roots':[{'name':'me', 'name':'you', 'type':'file', "
+                        "'external-contents':'blah' } ] }",
+                        Lower);
+  EXPECT_EQ(nullptr, FS.get());
+
+  // missing version
+  FS = getFromYAMLRawString("{ 'roots':[] }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+
+  // bad version number
+  FS = getFromYAMLRawString("{ 'version':'foo', 'roots':[] }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLRawString("{ 'version':-1, 'roots':[] }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  FS = getFromYAMLRawString("{ 'version':100000, 'roots':[] }", Lower);
+  EXPECT_EQ(nullptr, FS.get());
+  EXPECT_EQ(24, NumDiagnostics);
+}
+
+TEST_F(VFSFromYAMLTest, UseExternalName) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addRegularFile("//root/external/file");
+
+  IntrusiveRefCntPtr<vfs::FileSystem> FS =
+      getFromYAMLString("{ 'roots': [\n"
+                        "  { 'type': 'file', 'name': '//root/A',\n"
+                        "    'external-contents': '//root/external/file'\n"
+                        "  },\n"
+                        "  { 'type': 'file', 'name': '//root/B',\n"
+                        "    'use-external-name': true,\n"
+                        "    'external-contents': '//root/external/file'\n"
+                        "  },\n"
+                        "  { 'type': 'file', 'name': '//root/C',\n"
+                        "    'use-external-name': false,\n"
+                        "    'external-contents': '//root/external/file'\n"
+                        "  }\n"
+                        "] }",
+                        Lower);
+  ASSERT_TRUE(nullptr != FS.get());
+
+  // default true
+  EXPECT_EQ("//root/external/file", FS->status("//root/A")->getName());
+  // explicit
+  EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
+  EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
+
+  // global configuration
+  FS = getFromYAMLString("{ 'use-external-names': false,\n"
+                         "  'roots': [\n"
+                         "  { 'type': 'file', 'name': '//root/A',\n"
+                         "    'external-contents': '//root/external/file'\n"
+                         "  },\n"
+                         "  { 'type': 'file', 'name': '//root/B',\n"
+                         "    'use-external-name': true,\n"
+                         "    'external-contents': '//root/external/file'\n"
+                         "  },\n"
+                         "  { 'type': 'file', 'name': '//root/C',\n"
+                         "    'use-external-name': false,\n"
+                         "    'external-contents': '//root/external/file'\n"
+                         "  }\n"
+                         "] }",
+                         Lower);
+  ASSERT_TRUE(nullptr != FS.get());
+
+  // default
+  EXPECT_EQ("//root/A", FS->status("//root/A")->getName());
+  // explicit
+  EXPECT_EQ("//root/external/file", FS->status("//root/B")->getName());
+  EXPECT_EQ("//root/C", FS->status("//root/C")->getName());
+}
+
+TEST_F(VFSFromYAMLTest, MultiComponentPath) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addRegularFile("//root/other");
+
+  // file in roots
+  IntrusiveRefCntPtr<vfs::FileSystem> FS =
+      getFromYAMLString("{ 'roots': [\n"
+                        "  { 'type': 'file', 'name': '//root/path/to/file',\n"
+                        "    'external-contents': '//root/other' }]\n"
+                        "}",
+                        Lower);
+  ASSERT_TRUE(nullptr != FS.get());
+  EXPECT_FALSE(FS->status("//root/path/to/file").getError());
+  EXPECT_FALSE(FS->status("//root/path/to").getError());
+  EXPECT_FALSE(FS->status("//root/path").getError());
+  EXPECT_FALSE(FS->status("//root/").getError());
+
+  // at the start
+  FS = getFromYAMLString(
+      "{ 'roots': [\n"
+      "  { 'type': 'directory', 'name': '//root/path/to',\n"
+      "    'contents': [ { 'type': 'file', 'name': 'file',\n"
+      "                    'external-contents': '//root/other' }]}]\n"
+      "}",
+      Lower);
+  ASSERT_TRUE(nullptr != FS.get());
+  EXPECT_FALSE(FS->status("//root/path/to/file").getError());
+  EXPECT_FALSE(FS->status("//root/path/to").getError());
+  EXPECT_FALSE(FS->status("//root/path").getError());
+  EXPECT_FALSE(FS->status("//root/").getError());
+
+  // at the end
+  FS = getFromYAMLString(
+      "{ 'roots': [\n"
+      "  { 'type': 'directory', 'name': '//root/',\n"
+      "    'contents': [ { 'type': 'file', 'name': 'path/to/file',\n"
+      "                    'external-contents': '//root/other' }]}]\n"
+      "}",
+      Lower);
+  ASSERT_TRUE(nullptr != FS.get());
+  EXPECT_FALSE(FS->status("//root/path/to/file").getError());
+  EXPECT_FALSE(FS->status("//root/path/to").getError());
+  EXPECT_FALSE(FS->status("//root/path").getError());
+  EXPECT_FALSE(FS->status("//root/").getError());
+}
+
+TEST_F(VFSFromYAMLTest, TrailingSlashes) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addRegularFile("//root/other");
+
+  // file in roots
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+      "{ 'roots': [\n"
+      "  { 'type': 'directory', 'name': '//root/path/to////',\n"
+      "    'contents': [ { 'type': 'file', 'name': 'file',\n"
+      "                    'external-contents': '//root/other' }]}]\n"
+      "}",
+      Lower);
+  ASSERT_TRUE(nullptr != FS.get());
+  EXPECT_FALSE(FS->status("//root/path/to/file").getError());
+  EXPECT_FALSE(FS->status("//root/path/to").getError());
+  EXPECT_FALSE(FS->status("//root/path").getError());
+  EXPECT_FALSE(FS->status("//root/").getError());
+}
+
+TEST_F(VFSFromYAMLTest, DirectoryIteration) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addDirectory("//root/");
+  Lower->addDirectory("//root/foo");
+  Lower->addDirectory("//root/foo/bar");
+  Lower->addRegularFile("//root/foo/bar/a");
+  Lower->addRegularFile("//root/foo/bar/b");
+  Lower->addRegularFile("//root/file3");
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+      "{ 'use-external-names': false,\n"
+      "  'roots': [\n"
+      "{\n"
+      "  'type': 'directory',\n"
+      "  'name': '//root/',\n"
+      "  'contents': [ {\n"
+      "                  'type': 'file',\n"
+      "                  'name': 'file1',\n"
+      "                  'external-contents': '//root/foo/bar/a'\n"
+      "                },\n"
+      "                {\n"
+      "                  'type': 'file',\n"
+      "                  'name': 'file2',\n"
+      "                  'external-contents': '//root/foo/bar/b'\n"
+      "                }\n"
+      "              ]\n"
+      "}\n"
+      "]\n"
+      "}",
+      Lower);
+  ASSERT_TRUE(FS.get() != nullptr);
+
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(FS);
+
+  std::error_code EC;
+  checkContents(O->dir_begin("//root/", EC),
+                {"//root/file1", "//root/file2", "//root/file3", "//root/foo"});
+
+  checkContents(O->dir_begin("//root/foo/bar", EC),
+                {"//root/foo/bar/a", "//root/foo/bar/b"});
+}
+
+TEST_F(VFSFromYAMLTest, DirectoryIterationSameDirMultipleEntries) {
+  // https://llvm.org/bugs/show_bug.cgi?id=27725
+  if (!supportsSameDirMultipleYAMLEntries())
+    return;
+
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addDirectory("//root/zab");
+  Lower->addDirectory("//root/baz");
+  Lower->addRegularFile("//root/zab/a");
+  Lower->addRegularFile("//root/zab/b");
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+      "{ 'use-external-names': false,\n"
+      "  'roots': [\n"
+      "{\n"
+      "  'type': 'directory',\n"
+      "  'name': '//root/baz/',\n"
+      "  'contents': [ {\n"
+      "                  'type': 'file',\n"
+      "                  'name': 'x',\n"
+      "                  'external-contents': '//root/zab/a'\n"
+      "                }\n"
+      "              ]\n"
+      "},\n"
+      "{\n"
+      "  'type': 'directory',\n"
+      "  'name': '//root/baz/',\n"
+      "  'contents': [ {\n"
+      "                  'type': 'file',\n"
+      "                  'name': 'y',\n"
+      "                  'external-contents': '//root/zab/b'\n"
+      "                }\n"
+      "              ]\n"
+      "}\n"
+      "]\n"
+      "}",
+      Lower);
+  ASSERT_TRUE(FS.get() != nullptr);
+
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(FS);
+
+  std::error_code EC;
+
+  checkContents(O->dir_begin("//root/baz/", EC),
+                {"//root/baz/x", "//root/baz/y"});
+}
+
+TEST_F(VFSFromYAMLTest, RecursiveDirectoryIterationLevel) {
+
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  Lower->addDirectory("//root/a");
+  Lower->addDirectory("//root/a/b");
+  Lower->addDirectory("//root/a/b/c");
+  Lower->addRegularFile("//root/a/b/c/file");
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+      "{ 'use-external-names': false,\n"
+      "  'roots': [\n"
+      "{\n"
+      "  'type': 'directory',\n"
+      "  'name': '//root/a/b/c/',\n"
+      "  'contents': [ {\n"
+      "                  'type': 'file',\n"
+      "                  'name': 'file',\n"
+      "                  'external-contents': '//root/a/b/c/file'\n"
+      "                }\n"
+      "              ]\n"
+      "},\n"
+      "]\n"
+      "}",
+      Lower);
+  ASSERT_TRUE(FS.get() != nullptr);
+
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
+      new vfs::OverlayFileSystem(Lower));
+  O->pushOverlay(FS);
+
+  std::error_code EC;
+
+  // Test recursive_directory_iterator level()
+  vfs::recursive_directory_iterator I = vfs::recursive_directory_iterator(
+                                        *O, "//root", EC),
+                                    E;
+  ASSERT_FALSE(EC);
+  for (int l = 0; I != E; I.increment(EC), ++l) {
+    ASSERT_FALSE(EC);
+    EXPECT_EQ(I.level(), l);
+  }
+  EXPECT_EQ(I, E);
+}
+
+TEST_F(VFSFromYAMLTest, RelativePaths) {
+  IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
+  // Filename at root level without a parent directory.
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
+      "{ 'roots': [\n"
+      "  { 'type': 'file', 'name': 'file-not-in-directory.h',\n"
+      "    'external-contents': '//root/external/file'\n"
+      "  }\n"
+      "] }",
+      Lower);
+  EXPECT_EQ(nullptr, FS.get());
+
+  // Relative file path.
+  FS = getFromYAMLString("{ 'roots': [\n"
+                         "  { 'type': 'file', 'name': 'relative/file/path.h',\n"
+                         "    'external-contents': '//root/external/file'\n"
+                         "  }\n"
+                         "] }",
+                         Lower);
+  EXPECT_EQ(nullptr, FS.get());
+
+  // Relative directory path.
+  FS = getFromYAMLString(
+      "{ 'roots': [\n"
+      "  { 'type': 'directory', 'name': 'relative/directory/path.h',\n"
+      "    'contents': []\n"
+      "  }\n"
+      "] }",
+      Lower);
+  EXPECT_EQ(nullptr, FS.get());
+
+  EXPECT_EQ(3, NumDiagnostics);
+}
