r201618 - Initial implementation of virtual file system

Ben Langmuir blangmuir at apple.com
Thu Feb 20 14:08:41 PST 2014


Hi Juergen,

Sorry about the breakage.  I know I broke LLDB for the same reason.  I’ve changed how I handle setting up the VFS in the compiler instance so that it shouldn’t require intervention from clients that don’t care about the VFS and recommitted as r201818 (exactly 200 revisions from the initial commit, cool!).  I’ll keep an eye on the buildbots ;)

Ben

On Feb 19, 2014, at 9:35 PM, Juergen Ributzka <juergen at apple.com> wrote:

> Hi Ben,
> 
> I reverted your changes in r201755, because an assertion in your code kept failing on our internal build bots. I send you a separate email with the failing build bot.
> 
> -Juergen
> 
> On Feb 18, 2014, at 4:10 PM, Ben Langmuir <blangmuir at apple.com> wrote:
> 
>> Author: benlangmuir
>> Date: Tue Feb 18 18:10:30 2014
>> New Revision: 201618
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=201618&view=rev
>> Log:
>> Initial implementation of virtual file system
>> 
>> This adds the minimum virtual file system support to start migrating
>> FileManager onto the VFS.
>> 
>> Originally discussed here:
>> http://lists.cs.uiuc.edu/pipermail/cfe-dev/2014-February/035188.html
>> 
>> Differential Revision: http://llvm-reviews.chandlerc.com/D2745
>> 
>> Added:
>>   cfe/trunk/include/clang/Basic/VirtualFileSystem.h
>>   cfe/trunk/lib/Basic/VirtualFileSystem.cpp
>> Modified:
>>   cfe/trunk/include/clang/Basic/FileManager.h
>>   cfe/trunk/include/clang/Basic/FileSystemStatCache.h
>>   cfe/trunk/include/clang/Frontend/CompilerInstance.h
>>   cfe/trunk/lib/Basic/CMakeLists.txt
>>   cfe/trunk/lib/Basic/FileManager.cpp
>>   cfe/trunk/lib/Basic/FileSystemStatCache.cpp
>>   cfe/trunk/lib/Frontend/ASTUnit.cpp
>>   cfe/trunk/lib/Frontend/CacheTokens.cpp
>>   cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp
>>   cfe/trunk/lib/Frontend/CompilerInstance.cpp
>>   cfe/trunk/lib/Frontend/FrontendAction.cpp
>>   cfe/trunk/lib/Lex/PTHLexer.cpp
>>   cfe/trunk/lib/Serialization/ModuleManager.cpp
>>   cfe/trunk/unittests/Basic/FileManagerTest.cpp
>> 
>> Modified: cfe/trunk/include/clang/Basic/FileManager.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/FileManager.h?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/FileManager.h (original)
>> +++ cfe/trunk/include/clang/Basic/FileManager.h Tue Feb 18 18:10:30 2014
>> @@ -17,6 +17,7 @@
>> 
>> #include "clang/Basic/FileSystemOptions.h"
>> #include "clang/Basic/LLVM.h"
>> +#include "clang/Basic/VirtualFileSystem.h"
>> #include "llvm/ADT/DenseMap.h"
>> #include "llvm/ADT/IntrusiveRefCntPtr.h"
>> #include "llvm/ADT/OwningPtr.h"
>> @@ -24,7 +25,6 @@
>> #include "llvm/ADT/StringMap.h"
>> #include "llvm/ADT/StringRef.h"
>> #include "llvm/Support/Allocator.h"
>> -#include "llvm/Support/FileSystem.h"
>> // FIXME: Enhance libsystem to support inode and other fields in stat.
>> #include <sys/types.h>
>> 
>> @@ -55,7 +55,7 @@ public:
>> /// \brief Cached information about one file (either on disk
>> /// or in the virtual file system).
>> ///
>> -/// If the 'FD' member is valid, then this FileEntry has an open file
>> +/// If the 'File' member is valid, then this FileEntry has an open file
>> /// descriptor for the file.
>> class FileEntry {
>>  const char *Name;           // Name of the file.
>> @@ -67,31 +67,33 @@ class FileEntry {
>>  bool IsNamedPipe;
>>  bool InPCH;
>> 
>> -  /// FD - The file descriptor for the file entry if it is opened and owned
>> -  /// by the FileEntry.  If not, this is set to -1.
>> -  mutable int FD;
>> +  /// \brief The open file, if it is owned by the \p FileEntry.
>> +  mutable OwningPtr<vfs::File> File;
>>  friend class FileManager;
>> 
>> +  void closeFile() const {
>> +    File.reset(0); // rely on destructor to close File
>> +  }
>> +
>> public:
>>  FileEntry(llvm::sys::fs::UniqueID UniqueID, bool IsNamedPipe, bool InPCH)
>> -      : Name(0), UniqueID(UniqueID), IsNamedPipe(IsNamedPipe), InPCH(InPCH),
>> -        FD(-1) {}
>> +      : Name(0), UniqueID(UniqueID), IsNamedPipe(IsNamedPipe), InPCH(InPCH)
>> +  {}
>>  // Add a default constructor for use with llvm::StringMap
>>  FileEntry()
>> -      : Name(0), UniqueID(0, 0), IsNamedPipe(false), InPCH(false), FD(-1) {}
>> +      : Name(0), UniqueID(0, 0), IsNamedPipe(false), InPCH(false)
>> +  {}
>> 
>>  FileEntry(const FileEntry &FE) {
>>    memcpy(this, &FE, sizeof(FE));
>> -    assert(FD == -1 && "Cannot copy a file-owning FileEntry");
>> +    assert(!File && "Cannot copy a file-owning FileEntry");
>>  }
>> 
>>  void operator=(const FileEntry &FE) {
>>    memcpy(this, &FE, sizeof(FE));
>> -    assert(FD == -1 && "Cannot assign a file-owning FileEntry");
>> +    assert(!File && "Cannot assign a file-owning FileEntry");
>>  }
>> 
>> -  ~FileEntry();
>> -
>>  const char *getName() const { return Name; }
>>  off_t getSize() const { return Size; }
>>  unsigned getUID() const { return UID; }
>> @@ -119,6 +121,7 @@ struct FileData;
>> /// as a single file.
>> ///
>> class FileManager : public RefCountedBase<FileManager> {
>> +  IntrusiveRefCntPtr<vfs::FileSystem> FS;
>>  FileSystemOptions FileSystemOpts;
>> 
>>  class UniqueDirContainer;
>> @@ -172,14 +175,15 @@ class FileManager : public RefCountedBas
>>  OwningPtr<FileSystemStatCache> StatCache;
>> 
>>  bool getStatValue(const char *Path, FileData &Data, bool isFile,
>> -                    int *FileDescriptor);
>> +                    vfs::File **F);
>> 
>>  /// Add all ancestors of the given path (pointing to either a file
>>  /// or a directory) as virtual directories.
>>  void addAncestorsAsVirtualDirs(StringRef Path);
>> 
>> public:
>> -  FileManager(const FileSystemOptions &FileSystemOpts);
>> +  FileManager(const FileSystemOptions &FileSystemOpts,
>> +              llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS = 0);
>>  ~FileManager();
>> 
>>  /// \brief Installs the provided FileSystemStatCache object within
>> @@ -248,7 +252,7 @@ public:
>>  ///
>>  /// \returns false on success, true on error.
>>  bool getNoncachedStatValue(StringRef Path,
>> -                             llvm::sys::fs::file_status &Result);
>> +                             vfs::Status &Result);
>> 
>>  /// \brief Remove the real file \p Entry from the cache.
>>  void invalidateCache(const FileEntry *Entry);
>> 
>> Modified: cfe/trunk/include/clang/Basic/FileSystemStatCache.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/FileSystemStatCache.h?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/FileSystemStatCache.h (original)
>> +++ cfe/trunk/include/clang/Basic/FileSystemStatCache.h Tue Feb 18 18:10:30 2014
>> @@ -24,6 +24,11 @@
>> 
>> namespace clang {
>> 
>> +namespace vfs {
>> +class File;
>> +class FileSystem;
>> +}
>> +
>> struct FileData {
>>  uint64_t Size;
>>  time_t ModTime;
>> @@ -57,10 +62,11 @@ public:
>>  /// If isFile is true, then this lookup should only return success for files
>>  /// (not directories).  If it is false this lookup should only return
>>  /// success for directories (not files).  On a successful file lookup, the
>> -  /// implementation can optionally fill in FileDescriptor with a valid
>> -  /// descriptor and the client guarantees that it will close it.
>> +  /// implementation can optionally fill in \p F with a valid \p File object and
>> +  /// the client guarantees that it will close it.
>>  static bool get(const char *Path, FileData &Data, bool isFile,
>> -                  int *FileDescriptor, FileSystemStatCache *Cache);
>> +                  vfs::File **F, FileSystemStatCache *Cache,
>> +                  vfs::FileSystem &FS);
>> 
>>  /// \brief Sets the next stat call cache in the chain of stat caches.
>>  /// Takes ownership of the given stat cache.
>> @@ -78,17 +84,16 @@ public:
>> 
>> protected:
>>  virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
>> -                               int *FileDescriptor) = 0;
>> +                               vfs::File **F, vfs::FileSystem &FS) = 0;
>> 
>>  LookupResult statChained(const char *Path, FileData &Data, bool isFile,
>> -                           int *FileDescriptor) {
>> +                           vfs::File **F, vfs::FileSystem &FS) {
>>    if (FileSystemStatCache *Next = getNextStatCache())
>> -      return Next->getStat(Path, Data, isFile, FileDescriptor);
>> +      return Next->getStat(Path, Data, isFile, F, FS);
>> 
>>    // If we hit the end of the list of stat caches to try, just compute and
>>    // return it without a cache.
>> -    return get(Path, Data, isFile, FileDescriptor, 0) ? CacheMissing
>> -                                                      : CacheExists;
>> +    return get(Path, Data, isFile, F, 0, FS) ? CacheMissing : CacheExists;
>>  }
>> };
>> 
>> @@ -107,7 +112,7 @@ public:
>>  iterator end() const { return StatCalls.end(); }
>> 
>>  virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
>> -                               int *FileDescriptor);
>> +                               vfs::File **F, vfs::FileSystem &FS);
>> };
>> 
>> } // end namespace clang
>> 
>> Added: cfe/trunk/include/clang/Basic/VirtualFileSystem.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/VirtualFileSystem.h?rev=201618&view=auto
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/VirtualFileSystem.h (added)
>> +++ cfe/trunk/include/clang/Basic/VirtualFileSystem.h Tue Feb 18 18:10:30 2014
>> @@ -0,0 +1,127 @@
>> +//===- 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
>> +/// \brief Defines the virtual file system interface vfs::FileSystem.
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_H
>> +#define LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_H
>> +
>> +#include "llvm/ADT/IntrusiveRefCntPtr.h"
>> +#include "llvm/Support/FileSystem.h"
>> +#include "llvm/Support/ErrorOr.h"
>> +
>> +namespace llvm {
>> +template <typename T> class OwningPtr;
>> +class MemoryBuffer;
>> +}
>> +
>> +namespace clang {
>> +namespace vfs {
>> +
>> +/// \brief The result of a \p status operation.
>> +class Status {
>> +  std::string Name;
>> +  std::string ExternalName;
>> +  llvm::sys::fs::UniqueID UID;
>> +  llvm::sys::TimeValue MTime;
>> +  uint32_t User;
>> +  uint32_t Group;
>> +  uint64_t Size;
>> +  llvm::sys::fs::file_type Type;
>> +  llvm::sys::fs::perms Perms;
>> +
>> +public:
>> +  Status() : Type(llvm::sys::fs::file_type::status_error) {}
>> +  Status(const llvm::sys::fs::file_status &Status);
>> +  Status(llvm::StringRef Name, llvm::StringRef RealName,
>> +         llvm::sys::fs::UniqueID UID, llvm::sys::TimeValue MTime,
>> +         uint32_t User, uint32_t Group, uint64_t Size,
>> +         llvm::sys::fs::file_type Type, llvm::sys::fs::perms Perms);
>> +
>> +  /// \brief Returns the name this status was looked up by.
>> +  llvm::StringRef getName() const { return Name; }
>> +
>> +  /// \brief Returns the name to use outside the compiler.
>> +  ///
>> +  /// For example, in diagnostics or debug info we should use this name.
>> +  llvm::StringRef getExternalName() const { return ExternalName; }
>> +
>> +  void setName(llvm::StringRef N) { Name = N; }
>> +  void setExternalName(llvm::StringRef N) { ExternalName = N; }
>> +
>> +  /// @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::TimeValue 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; }
>> +  void setType(llvm::sys::fs::file_type v) { Type = v; }
>> +  void setPermissions(llvm::sys::fs::perms p) { Perms = p; }
>> +  /// @}
>> +  /// @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;
>> +  /// @}
>> +};
>> +
>> +/// \brief Represents an open file.
>> +class File {
>> +public:
>> +  /// \brief 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();
>> +  /// \brief Get the status of the file.
>> +  virtual llvm::ErrorOr<Status> status() = 0;
>> +  /// \brief Get the contents of the file as a \p MemoryBuffer.
>> +  virtual llvm::error_code
>> +  getBuffer(const llvm::Twine &Name,
>> +            llvm::OwningPtr<llvm::MemoryBuffer> &Result, int64_t FileSize = -1,
>> +            bool RequiresNullTerminator = true) = 0;
>> +  /// \brief Closes the file.
>> +  virtual llvm::error_code close() = 0;
>> +};
>> +
>> +/// \brief The virtual file system interface.
>> +class FileSystem : public llvm::RefCountedBase<FileSystem> {
>> +public:
>> +  virtual ~FileSystem();
>> +
>> +  /// \brief Get the status of the entry at \p Path, if one exists.
>> +  virtual llvm::ErrorOr<Status> status(const llvm::Twine &Path) = 0;
>> +  /// \brief Get a \p File object for the file at \p Path, if one exists.
>> +  virtual llvm::error_code openFileForRead(const llvm::Twine &Path,
>> +                                           llvm::OwningPtr<File> &Result) = 0;
>> +
>> +  /// This is a convenience method that opens a file, gets its content and then
>> +  /// closes the file.
>> +  llvm::error_code getBufferForFile(const llvm::Twine &Name,
>> +                                    llvm::OwningPtr<llvm::MemoryBuffer> &Result,
>> +                                    int64_t FileSize = -1,
>> +                                    bool RequiresNullTerminator = true);
>> +};
>> +
>> +/// \brief Gets an \p vfs::FileSystem for the 'real' file system, as seen by
>> +/// the operating system.
>> +llvm::IntrusiveRefCntPtr<FileSystem> getRealFileSystem();
>> +
>> +} // end namespace vfs
>> +} // end namespace clang
>> +#endif // LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_H
>> 
>> Modified: cfe/trunk/include/clang/Frontend/CompilerInstance.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CompilerInstance.h?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Frontend/CompilerInstance.h (original)
>> +++ cfe/trunk/include/clang/Frontend/CompilerInstance.h Tue Feb 18 18:10:30 2014
>> @@ -75,6 +75,9 @@ class CompilerInstance : public ModuleLo
>>  /// The target being compiled for.
>>  IntrusiveRefCntPtr<TargetInfo> Target;
>> 
>> +  /// The virtual file system.
>> +  IntrusiveRefCntPtr<vfs::FileSystem> VirtualFileSystem;
>> +
>>  /// The file manager.
>>  IntrusiveRefCntPtr<FileManager> FileMgr;
>> 
>> @@ -314,6 +317,23 @@ public:
>>  void setTarget(TargetInfo *Value);
>> 
>>  /// }
>> +  /// @name Virtual File System
>> +  /// {
>> +
>> +  bool hasVirtualFileSystem() const { return VirtualFileSystem != 0; }
>> +
>> +  vfs::FileSystem &getVirtualFileSystem() const {
>> +    assert(hasVirtualFileSystem() &&
>> +           "Compiler instance has no virtual file system");
>> +    return *VirtualFileSystem;
>> +  }
>> +
>> +  /// \brief Replace the current virtual file system.
>> +  void setVirtualFileSystem(IntrusiveRefCntPtr<vfs::FileSystem> FS) {
>> +    VirtualFileSystem = FS;
>> +  }
>> +
>> +  /// }
>>  /// @name File Manager
>>  /// {
>> 
>> @@ -527,6 +547,10 @@ public:
>>                    bool ShouldOwnClient = true,
>>                    const CodeGenOptions *CodeGenOpts = 0);
>> 
>> +  /// Create a virtual file system and replace any existing one with it.
>> +  /// The default is to use the real file system.
>> +  void createVirtualFileSystem();
>> +
>>  /// Create the file manager and replace any existing one with it.
>>  void createFileManager();
>> 
>> 
>> Modified: cfe/trunk/lib/Basic/CMakeLists.txt
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/CMakeLists.txt?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Basic/CMakeLists.txt (original)
>> +++ cfe/trunk/lib/Basic/CMakeLists.txt Tue Feb 18 18:10:30 2014
>> @@ -23,6 +23,7 @@ add_clang_library(clangBasic
>>  TokenKinds.cpp
>>  Version.cpp
>>  VersionTuple.cpp
>> +  VirtualFileSystem.cpp
>>  )
>> 
>> # Determine Subversion revision.
>> 
>> Modified: cfe/trunk/lib/Basic/FileManager.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/FileManager.cpp?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Basic/FileManager.cpp (original)
>> +++ cfe/trunk/lib/Basic/FileManager.cpp Tue Feb 18 18:10:30 2014
>> @@ -30,19 +30,6 @@
>> #include <set>
>> #include <string>
>> 
>> -// FIXME: This is terrible, we need this for ::close.
>> -#if !defined(_MSC_VER) && !defined(__MINGW32__)
>> -#include <unistd.h>
>> -#include <sys/uio.h>
>> -#else
>> -#include <io.h>
>> -#ifndef S_ISFIFO
>> -#define S_ISFIFO(x) (0)
>> -#endif
>> -#endif
>> -#if defined(LLVM_ON_UNIX)
>> -#include <limits.h>
>> -#endif
>> using namespace clang;
>> 
>> // FIXME: Enhance libsystem to support inode and other fields.
>> @@ -57,12 +44,6 @@ using namespace clang;
>> #define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1)
>> 
>> 
>> -FileEntry::~FileEntry() {
>> -  // If this FileEntry owns an open file descriptor that never got used, close
>> -  // it.
>> -  if (FD != -1) ::close(FD);
>> -}
>> -
>> class FileManager::UniqueDirContainer {
>>  /// UniqueDirs - Cache from ID's to existing directories/files.
>>  std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueDirs;
>> @@ -101,13 +82,19 @@ public:
>> // Common logic.
>> //===----------------------------------------------------------------------===//
>> 
>> -FileManager::FileManager(const FileSystemOptions &FSO)
>> -  : FileSystemOpts(FSO),
>> +FileManager::FileManager(const FileSystemOptions &FSO,
>> +                         IntrusiveRefCntPtr<vfs::FileSystem> FS)
>> +  : FS(FS), FileSystemOpts(FSO),
>>    UniqueRealDirs(*new UniqueDirContainer()),
>>    UniqueRealFiles(*new UniqueFileContainer()),
>>    SeenDirEntries(64), SeenFileEntries(64), NextFileUID(0) {
>>  NumDirLookups = NumFileLookups = 0;
>>  NumDirCacheMisses = NumFileCacheMisses = 0;
>> +
>> +  // If the caller doesn't provide a virtual file system, just grab the real
>> +  // file system.
>> +  if (!FS)
>> +    this->FS = vfs::getRealFileSystem();
>> }
>> 
>> FileManager::~FileManager() {
>> @@ -309,10 +296,9 @@ const FileEntry *FileManager::getFile(St
>>  // FIXME: This will reduce the # syscalls.
>> 
>>  // Nope, there isn't.  Check to see if the file exists.
>> -  int FileDescriptor = -1;
>> +  vfs::File *F = 0;
>>  FileData Data;
>> -  if (getStatValue(InterndFileName, Data, true,
>> -                   openFile ? &FileDescriptor : 0)) {
>> +  if (getStatValue(InterndFileName, Data, true, openFile ? &F : 0)) {
>>    // There's no real file at the given path.
>>    if (!CacheFailure)
>>      SeenFileEntries.erase(Filename);
>> @@ -320,10 +306,7 @@ const FileEntry *FileManager::getFile(St
>>    return 0;
>>  }
>> 
>> -  if (FileDescriptor != -1 && !openFile) {
>> -    close(FileDescriptor);
>> -    FileDescriptor = -1;
>> -  }
>> +  assert(openFile || !F && "undesired open file");
>> 
>>  // It exists.  See if we have already opened a file with the same inode.
>>  // This occurs when one dir is symlinked to another, for example.
>> @@ -333,8 +316,8 @@ const FileEntry *FileManager::getFile(St
>>  NamedFileEnt.setValue(&UFE);
>>  if (UFE.getName()) { // Already have an entry with this inode, return it.
>>    // If the stat process opened the file, close it to avoid a FD leak.
>> -    if (FileDescriptor != -1)
>> -      close(FileDescriptor);
>> +    if (F)
>> +      delete F;
>> 
>>    return &UFE;
>>  }
>> @@ -347,7 +330,7 @@ const FileEntry *FileManager::getFile(St
>>  UFE.ModTime = Data.ModTime;
>>  UFE.Dir     = DirInfo;
>>  UFE.UID     = NextFileUID++;
>> -  UFE.FD      = FileDescriptor;
>> +  UFE.File.reset(F);
>>  return &UFE;
>> }
>> 
>> @@ -393,10 +376,8 @@ FileManager::getVirtualFile(StringRef Fi
>>    // If we had already opened this file, close it now so we don't
>>    // leak the descriptor. We're not going to use the file
>>    // descriptor anyway, since this is a virtual file.
>> -    if (UFE->FD != -1) {
>> -      close(UFE->FD);
>> -      UFE->FD = -1;
>> -    }
>> +    if (UFE->File)
>> +      UFE->closeFile();
>> 
>>    // If we already have an entry with this inode, return it.
>>    if (UFE->getName())
>> @@ -414,7 +395,7 @@ FileManager::getVirtualFile(StringRef Fi
>>  UFE->ModTime = ModificationTime;
>>  UFE->Dir     = DirInfo;
>>  UFE->UID     = NextFileUID++;
>> -  UFE->FD      = -1;
>> +  UFE->File.reset();
>>  return UFE;
>> }
>> 
>> @@ -444,20 +425,18 @@ getBufferForFile(const FileEntry *Entry,
>> 
>>  const char *Filename = Entry->getName();
>>  // If the file is already open, use the open file descriptor.
>> -  if (Entry->FD != -1) {
>> -    ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, FileSize);
>> +  if (Entry->File) {
>> +    ec = Entry->File->getBuffer(Filename, Result, FileSize);
>>    if (ErrorStr)
>>      *ErrorStr = ec.message();
>> -
>> -    close(Entry->FD);
>> -    Entry->FD = -1;
>> +    Entry->closeFile();
>>    return Result.take();
>>  }
>> 
>>  // Otherwise, open the file.
>> 
>>  if (FileSystemOpts.WorkingDir.empty()) {
>> -    ec = llvm::MemoryBuffer::getFile(Filename, Result, FileSize);
>> +    ec = FS->getBufferForFile(Filename, Result, FileSize);
>>    if (ec && ErrorStr)
>>      *ErrorStr = ec.message();
>>    return Result.take();
>> @@ -465,7 +444,7 @@ getBufferForFile(const FileEntry *Entry,
>> 
>>  SmallString<128> FilePath(Entry->getName());
>>  FixupRelativePath(FilePath);
>> -  ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, FileSize);
>> +  ec = FS->getBufferForFile(FilePath.str(), Result, FileSize);
>>  if (ec && ErrorStr)
>>    *ErrorStr = ec.message();
>>  return Result.take();
>> @@ -476,7 +455,7 @@ getBufferForFile(StringRef Filename, std
>>  OwningPtr<llvm::MemoryBuffer> Result;
>>  llvm::error_code ec;
>>  if (FileSystemOpts.WorkingDir.empty()) {
>> -    ec = llvm::MemoryBuffer::getFile(Filename, Result);
>> +    ec = FS->getBufferForFile(Filename, Result);
>>    if (ec && ErrorStr)
>>      *ErrorStr = ec.message();
>>    return Result.take();
>> @@ -484,7 +463,7 @@ getBufferForFile(StringRef Filename, std
>> 
>>  SmallString<128> FilePath(Filename);
>>  FixupRelativePath(FilePath);
>> -  ec = llvm::MemoryBuffer::getFile(FilePath.c_str(), Result);
>> +  ec = FS->getBufferForFile(FilePath.c_str(), Result);
>>  if (ec && ErrorStr)
>>    *ErrorStr = ec.message();
>>  return Result.take();
>> @@ -496,26 +475,29 @@ getBufferForFile(StringRef Filename, std
>> /// false if it's an existent real file.  If FileDescriptor is NULL,
>> /// do directory look-up instead of file look-up.
>> bool FileManager::getStatValue(const char *Path, FileData &Data, bool isFile,
>> -                               int *FileDescriptor) {
>> +                               vfs::File **F) {
>>  // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
>>  // absolute!
>>  if (FileSystemOpts.WorkingDir.empty())
>> -    return FileSystemStatCache::get(Path, Data, isFile, FileDescriptor,
>> -                                    StatCache.get());
>> +    return FileSystemStatCache::get(Path, Data, isFile, F,StatCache.get(), *FS);
>> 
>>  SmallString<128> FilePath(Path);
>>  FixupRelativePath(FilePath);
>> 
>> -  return FileSystemStatCache::get(FilePath.c_str(), Data, isFile,
>> -                                  FileDescriptor, StatCache.get());
>> +  return FileSystemStatCache::get(FilePath.c_str(), Data, isFile, F,
>> +                                  StatCache.get(), *FS);
>> }
>> 
>> bool FileManager::getNoncachedStatValue(StringRef Path,
>> -                                        llvm::sys::fs::file_status &Result) {
>> +                                        vfs::Status &Result) {
>>  SmallString<128> FilePath(Path);
>>  FixupRelativePath(FilePath);
>> 
>> -  return llvm::sys::fs::status(FilePath.c_str(), Result);
>> +  llvm::ErrorOr<vfs::Status> S = FS->status(FilePath.c_str());
>> +  if (!S)
>> +    return true;
>> +  Result = *S;
>> +  return false;
>> }
>> 
>> void FileManager::invalidateCache(const FileEntry *Entry) {
>> 
>> Modified: cfe/trunk/lib/Basic/FileSystemStatCache.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/FileSystemStatCache.cpp?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Basic/FileSystemStatCache.cpp (original)
>> +++ cfe/trunk/lib/Basic/FileSystemStatCache.cpp Tue Feb 18 18:10:30 2014
>> @@ -12,7 +12,7 @@
>> //===----------------------------------------------------------------------===//
>> 
>> #include "clang/Basic/FileSystemStatCache.h"
>> -#include "llvm/Support/FileSystem.h"
>> +#include "clang/Basic/VirtualFileSystem.h"
>> #include "llvm/Support/Path.h"
>> 
>> // FIXME: This is terrible, we need this for ::close.
>> @@ -30,13 +30,13 @@ using namespace clang;
>> 
>> void FileSystemStatCache::anchor() { }
>> 
>> -static void copyStatusToFileData(const llvm::sys::fs::file_status &Status,
>> +static void copyStatusToFileData(const vfs::Status &Status,
>>                                 FileData &Data) {
>>  Data.Size = Status.getSize();
>>  Data.ModTime = Status.getLastModificationTime().toEpochTime();
>>  Data.UniqueID = Status.getUniqueID();
>> -  Data.IsDirectory = is_directory(Status);
>> -  Data.IsNamedPipe = Status.type() == llvm::sys::fs::file_type::fifo_file;
>> +  Data.IsDirectory = Status.isDirectory();
>> +  Data.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
>>  Data.InPCH = false;
>> }
>> 
>> @@ -50,22 +50,23 @@ static void copyStatusToFileData(const l
>> /// implementation can optionally fill in FileDescriptor with a valid
>> /// descriptor and the client guarantees that it will close it.
>> bool FileSystemStatCache::get(const char *Path, FileData &Data, bool isFile,
>> -                              int *FileDescriptor, FileSystemStatCache *Cache) {
>> +                              vfs::File **F, FileSystemStatCache *Cache,
>> +                              vfs::FileSystem &FS) {
>>  LookupResult R;
>>  bool isForDir = !isFile;
>> 
>>  // If we have a cache, use it to resolve the stat query.
>>  if (Cache)
>> -    R = Cache->getStat(Path, Data, isFile, FileDescriptor);
>> -  else if (isForDir || !FileDescriptor) {
>> +    R = Cache->getStat(Path, Data, isFile, F, FS);
>> +  else if (isForDir || !F) {
>>    // If this is a directory or a file descriptor is not needed and we have
>>    // no cache, just go to the file system.
>> -    llvm::sys::fs::file_status Status;
>> -    if (llvm::sys::fs::status(Path, Status)) {
>> +    llvm::ErrorOr<vfs::Status> Status = FS.status(Path);
>> +    if (!Status) {
>>      R = CacheMissing;
>>    } else {
>>      R = CacheExists;
>> -      copyStatusToFileData(Status, Data);
>> +      copyStatusToFileData(*Status, Data);
>>    }
>>  } else {
>>    // Otherwise, we have to go to the filesystem.  We can always just use
>> @@ -75,7 +76,8 @@ bool FileSystemStatCache::get(const char
>>    //
>>    // Because of this, check to see if the file exists with 'open'.  If the
>>    // open succeeds, use fstat to get the stat info.
>> -    llvm::error_code EC = llvm::sys::fs::openFileForRead(Path, *FileDescriptor);
>> +    llvm::OwningPtr<vfs::File> OwnedFile;
>> +    llvm::error_code EC = FS.openFileForRead(Path, OwnedFile);
>> 
>>    if (EC) {
>>      // If the open fails, our "stat" fails.
>> @@ -84,16 +86,16 @@ bool FileSystemStatCache::get(const char
>>      // Otherwise, the open succeeded.  Do an fstat to get the information
>>      // about the file.  We'll end up returning the open file descriptor to the
>>      // client to do what they please with it.
>> -      llvm::sys::fs::file_status Status;
>> -      if (!llvm::sys::fs::status(*FileDescriptor, Status)) {
>> +      llvm::ErrorOr<vfs::Status> Status = OwnedFile->status();
>> +      if (Status) {
>>        R = CacheExists;
>> -        copyStatusToFileData(Status, Data);
>> +        copyStatusToFileData(*Status, Data);
>> +        *F = OwnedFile.take();
>>      } else {
>>        // fstat rarely fails.  If it does, claim the initial open didn't
>>        // succeed.
>>        R = CacheMissing;
>> -        ::close(*FileDescriptor);
>> -        *FileDescriptor = -1;
>> +        *F = 0;
>>      }
>>    }
>>  }
>> @@ -105,9 +107,9 @@ bool FileSystemStatCache::get(const char
>>  // demands.
>>  if (Data.IsDirectory != isForDir) {
>>    // If not, close the file if opened.
>> -    if (FileDescriptor && *FileDescriptor != -1) {
>> -      ::close(*FileDescriptor);
>> -      *FileDescriptor = -1;
>> +    if (F && *F) {
>> +      (*F)->close();
>> +      *F = 0;
>>    }
>> 
>>    return true;
>> @@ -118,8 +120,8 @@ bool FileSystemStatCache::get(const char
>> 
>> MemorizeStatCalls::LookupResult
>> MemorizeStatCalls::getStat(const char *Path, FileData &Data, bool isFile,
>> -                           int *FileDescriptor) {
>> -  LookupResult Result = statChained(Path, Data, isFile, FileDescriptor);
>> +                           vfs::File **F, vfs::FileSystem &FS) {
>> +  LookupResult Result = statChained(Path, Data, isFile, F, FS);
>> 
>>  // Do not cache failed stats, it is easy to construct common inconsistent
>>  // situations if we do, and they are not important for PCH performance (which
>> 
>> Added: cfe/trunk/lib/Basic/VirtualFileSystem.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/VirtualFileSystem.cpp?rev=201618&view=auto
>> ==============================================================================
>> --- cfe/trunk/lib/Basic/VirtualFileSystem.cpp (added)
>> +++ cfe/trunk/lib/Basic/VirtualFileSystem.cpp Tue Feb 18 18:10:30 2014
>> @@ -0,0 +1,162 @@
>> +//===- VirtualFileSystem.cpp - 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.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +// This file implements the VirtualFileSystem interface.
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "clang/Basic/VirtualFileSystem.h"
>> +#include "llvm/ADT/OwningPtr.h"
>> +#include "llvm/Support/MemoryBuffer.h"
>> +#include "llvm/Support/SourceMgr.h"
>> +#include "llvm/Support/Path.h"
>> +
>> +using namespace clang;
>> +using namespace clang::vfs;
>> +using namespace llvm;
>> +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, StringRef ExternalName,
>> +               UniqueID UID, sys::TimeValue MTime,
>> +               uint32_t User, uint32_t Group, uint64_t Size,
>> +               file_type Type, perms Perms)
>> +    : Name(Name), ExternalName(ExternalName), UID(UID), MTime(MTime),
>> +      User(User), Group(Group), Size(Size), Type(Type), Perms(Perms) {}
>> +
>> +bool Status::equivalent(const Status &Other) const {
>> +  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 Type == 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() {}
>> +
>> +FileSystem::~FileSystem() {}
>> +
>> +error_code FileSystem::getBufferForFile(const llvm::Twine &Name,
>> +                                        OwningPtr<MemoryBuffer> &Result,
>> +                                        int64_t FileSize,
>> +                                        bool RequiresNullTerminator) {
>> +  llvm::OwningPtr<File> F;
>> +  if (error_code EC = openFileForRead(Name, F))
>> +    return EC;
>> +
>> +  error_code EC = F->getBuffer(Name, Result, FileSize, RequiresNullTerminator);
>> +  return EC;
>> +}
>> +
>> +//===-----------------------------------------------------------------------===/
>> +// RealFileSystem implementation
>> +//===-----------------------------------------------------------------------===/
>> +
>> +/// \brief Wrapper around a raw file descriptor.
>> +class RealFile : public File {
>> +  int FD;
>> +  friend class RealFileSystem;
>> +  RealFile(int FD) : FD(FD) {
>> +    assert(FD >= 0 && "Invalid or inactive file descriptor");
>> +  }
>> +public:
>> +  ~RealFile();
>> +  ErrorOr<Status> status() LLVM_OVERRIDE;
>> +  error_code getBuffer(const Twine &Name, OwningPtr<MemoryBuffer> &Result,
>> +                       int64_t FileSize = -1,
>> +                       bool RequiresNullTerminator = true) LLVM_OVERRIDE;
>> +  error_code close() LLVM_OVERRIDE;
>> +};
>> +RealFile::~RealFile() {
>> +  close();
>> +}
>> +
>> +ErrorOr<Status> RealFile::status() {
>> +  assert(FD != -1 && "cannot stat closed file");
>> +  file_status RealStatus;
>> +  if (error_code EC = sys::fs::status(FD, RealStatus))
>> +    return EC;
>> +  return Status(RealStatus);
>> +}
>> +
>> +error_code RealFile::getBuffer(const Twine &Name,
>> +                               OwningPtr<MemoryBuffer> &Result,
>> +                               int64_t FileSize, bool RequiresNullTerminator) {
>> +  assert(FD != -1 && "cannot get buffer for closed file");
>> +  return MemoryBuffer::getOpenFile(FD, Name.str().c_str(), Result, FileSize,
>> +                                   RequiresNullTerminator);
>> +}
>> +
>> +// FIXME: This is terrible, we need this for ::close.
>> +#if !defined(_MSC_VER) && !defined(__MINGW32__)
>> +#include <unistd.h>
>> +#include <sys/uio.h>
>> +#else
>> +#include <io.h>
>> +#ifndef S_ISFIFO
>> +#define S_ISFIFO(x) (0)
>> +#endif
>> +#endif
>> +error_code RealFile::close() {
>> +  if (::close(FD))
>> +    return error_code(errno, system_category());
>> +  FD = -1;
>> +  return error_code::success();
>> +}
>> +
>> +/// \brief The file system according to your operating system.
>> +class RealFileSystem : public FileSystem {
>> +public:
>> +  ErrorOr<Status> status(const Twine &Path) LLVM_OVERRIDE;
>> +  error_code openFileForRead(const Twine &Path, OwningPtr<File> &Result)
>> +    LLVM_OVERRIDE;
>> +};
>> +
>> +ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
>> +  sys::fs::file_status RealStatus;
>> +  if (error_code EC = sys::fs::status(Path, RealStatus))
>> +    return EC;
>> +  Status Result(RealStatus);
>> +  Result.setName(Path.str());
>> +  Result.setExternalName(Path.str());
>> +  return Result;
>> +}
>> +
>> +error_code RealFileSystem::openFileForRead(const Twine &Name,
>> +                                           OwningPtr<File> &Result) {
>> +  int FD;
>> +  if (error_code EC = sys::fs::openFileForRead(Name, FD))
>> +    return EC;
>> +  Result.reset(new RealFile(FD));
>> +  return error_code::success();
>> +}
>> +
>> +IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
>> +  static IntrusiveRefCntPtr<FileSystem> FS = new RealFileSystem();
>> +  return FS;
>> +}
>> 
>> Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
>> +++ cfe/trunk/lib/Frontend/ASTUnit.cpp Tue Feb 18 18:10:30 2014
>> @@ -20,6 +20,7 @@
>> #include "clang/Basic/Diagnostic.h"
>> #include "clang/Basic/TargetInfo.h"
>> #include "clang/Basic/TargetOptions.h"
>> +#include "clang/Basic/VirtualFileSystem.h"
>> #include "clang/Frontend/CompilerInstance.h"
>> #include "clang/Frontend/FrontendActions.h"
>> #include "clang/Frontend/FrontendDiagnostic.h"
>> @@ -37,7 +38,6 @@
>> #include "llvm/ADT/StringSet.h"
>> #include "llvm/Support/Atomic.h"
>> #include "llvm/Support/CrashRecoveryContext.h"
>> -#include "llvm/Support/FileSystem.h"
>> #include "llvm/Support/Host.h"
>> #include "llvm/Support/MemoryBuffer.h"
>> #include "llvm/Support/Mutex.h"
>> @@ -1421,7 +1421,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBuff
>>             REnd = PreprocessorOpts.remapped_file_end();
>>           !AnyFileChanged && R != REnd;
>>           ++R) {
>> -        llvm::sys::fs::file_status Status;
>> +        vfs::Status Status;
>>        if (FileMgr->getNoncachedStatValue(R->second, Status)) {
>>          // If we can't stat the file we're remapping to, assume that something
>>          // horrible happened.
>> @@ -1457,7 +1457,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBuff
>>        }
>> 
>>        // The file was not remapped; check whether it has changed on disk.
>> -        llvm::sys::fs::file_status Status;
>> +        vfs::Status Status;
>>        if (FileMgr->getNoncachedStatValue(F->first(), Status)) {
>>          // If we can't stat the file, assume that something horrible happened.
>>          AnyFileChanged = true;
>> 
>> Modified: cfe/trunk/lib/Frontend/CacheTokens.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CacheTokens.cpp?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Frontend/CacheTokens.cpp (original)
>> +++ cfe/trunk/lib/Frontend/CacheTokens.cpp Tue Feb 18 18:10:30 2014
>> @@ -516,8 +516,8 @@ public:
>>  ~StatListener() {}
>> 
>>  LookupResult getStat(const char *Path, FileData &Data, bool isFile,
>> -                       int *FileDescriptor) {
>> -    LookupResult Result = statChained(Path, Data, isFile, FileDescriptor);
>> +                       vfs::File **F, vfs::FileSystem &FS) {
>> +    LookupResult Result = statChained(Path, Data, isFile, F, FS);
>> 
>>    if (Result == CacheMissing) // Failed 'stat'.
>>      PM.insert(PTHEntryKeyVariant(Path), PTHEntry());
>> 
>> Modified: cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp (original)
>> +++ cfe/trunk/lib/Frontend/ChainedIncludesSource.cpp Tue Feb 18 18:10:30 2014
>> @@ -101,6 +101,7 @@ ChainedIncludesSource *ChainedIncludesSo
>>    Clang->setDiagnostics(Diags.getPtr());
>>    Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
>>                                                  &Clang->getTargetOpts()));
>> +    Clang->createVirtualFileSystem();
>>    Clang->createFileManager();
>>    Clang->createSourceManager(Clang->getFileManager());
>>    Clang->createPreprocessor();
>> 
>> Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
>> +++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Tue Feb 18 18:10:30 2014
>> @@ -194,9 +194,14 @@ CompilerInstance::createDiagnostics(Diag
>>  return Diags;
>> }
>> 
>> +void CompilerInstance::createVirtualFileSystem() {
>> +  VirtualFileSystem = vfs::getRealFileSystem();
>> +}
>> +
>> // File Manager
>> 
>> void CompilerInstance::createFileManager() {
>> +  assert(hasVirtualFileSystem() && "expected virtual file system");
>>  FileMgr = new FileManager(getFileSystemOpts());
>> }
>> 
>> @@ -867,6 +872,8 @@ static void compileModule(CompilerInstan
>>                                   ImportingInstance.getDiagnosticClient()),
>>                             /*ShouldOwnClient=*/true);
>> 
>> +  Instance.setVirtualFileSystem(&ImportingInstance.getVirtualFileSystem());
>> +
>>  // Note that this module is part of the module build stack, so that we
>>  // can detect cycles in the module graph.
>>  Instance.createFileManager(); // FIXME: Adopt file manager from importer?
>> 
>> Modified: cfe/trunk/lib/Frontend/FrontendAction.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendAction.cpp?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Frontend/FrontendAction.cpp (original)
>> +++ cfe/trunk/lib/Frontend/FrontendAction.cpp Tue Feb 18 18:10:30 2014
>> @@ -159,7 +159,6 @@ ASTConsumer* FrontendAction::CreateWrapp
>>  return new MultiplexConsumer(Consumers);
>> }
>> 
>> -
>> bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
>>                                     const FrontendInputFile &Input) {
>>  assert(!Instance && "Already processing a source file!");
>> @@ -213,6 +212,8 @@ bool FrontendAction::BeginSourceFile(Com
>>  }
>> 
>>  // Set up the file and source managers, if needed.
>> +  if (!CI.hasVirtualFileSystem())
>> +    CI.createVirtualFileSystem();
>>  if (!CI.hasFileManager())
>>    CI.createFileManager();
>>  if (!CI.hasSourceManager())
>> 
>> Modified: cfe/trunk/lib/Lex/PTHLexer.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PTHLexer.cpp?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Lex/PTHLexer.cpp (original)
>> +++ cfe/trunk/lib/Lex/PTHLexer.cpp Tue Feb 18 18:10:30 2014
>> @@ -675,13 +675,13 @@ public:
>>  ~PTHStatCache() {}
>> 
>>  LookupResult getStat(const char *Path, FileData &Data, bool isFile,
>> -                       int *FileDescriptor) {
>> +                       vfs::File **F, vfs::FileSystem &FS) {
>>    // Do the lookup for the file's data in the PTH file.
>>    CacheTy::iterator I = Cache.find(Path);
>> 
>>    // If we don't get a hit in the PTH file just forward to 'stat'.
>>    if (I == Cache.end())
>> -      return statChained(Path, Data, isFile, FileDescriptor);
>> +      return statChained(Path, Data, isFile, F, FS);
>> 
>>    const PTHStatData &D = *I;
>> 
>> 
>> Modified: cfe/trunk/lib/Serialization/ModuleManager.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ModuleManager.cpp?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Serialization/ModuleManager.cpp (original)
>> +++ cfe/trunk/lib/Serialization/ModuleManager.cpp Tue Feb 18 18:10:30 2014
>> @@ -89,7 +89,7 @@ ModuleManager::addModule(StringRef FileN
>>    New->InputFilesValidationTimestamp = 0;
>>    if (New->Kind == MK_Module) {
>>      std::string TimestampFilename = New->getTimestampFilename();
>> -      llvm::sys::fs::file_status Status;
>> +      vfs::Status Status;
>>      // A cached stat value would be fine as well.
>>      if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
>>        New->InputFilesValidationTimestamp =
>> 
>> Modified: cfe/trunk/unittests/Basic/FileManagerTest.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Basic/FileManagerTest.cpp?rev=201618&r1=201617&r2=201618&view=diff
>> ==============================================================================
>> --- cfe/trunk/unittests/Basic/FileManagerTest.cpp (original)
>> +++ cfe/trunk/unittests/Basic/FileManagerTest.cpp Tue Feb 18 18:10:30 2014
>> @@ -48,7 +48,7 @@ public:
>> 
>>  // Implement FileSystemStatCache::getStat().
>>  virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
>> -                               int *FileDescriptor) {
>> +                               vfs::File **F, vfs::FileSystem &FS) {
>>    if (StatCalls.count(Path) != 0) {
>>      Data = StatCalls[Path];
>>      return CacheExists;
>> 
>> 
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> 





More information about the cfe-commits mailing list