Home | History | Annotate | Line # | Download | only in Basic
      1 //===--- FileManager.h - File System Probing and Caching --------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 ///
      9 /// \file
     10 /// Defines the clang::FileManager interface and associated types.
     11 ///
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_CLANG_BASIC_FILEMANAGER_H
     15 #define LLVM_CLANG_BASIC_FILEMANAGER_H
     16 
     17 #include "clang/Basic/DirectoryEntry.h"
     18 #include "clang/Basic/FileEntry.h"
     19 #include "clang/Basic/FileSystemOptions.h"
     20 #include "clang/Basic/LLVM.h"
     21 #include "llvm/ADT/DenseMap.h"
     22 #include "llvm/ADT/IntrusiveRefCntPtr.h"
     23 #include "llvm/ADT/PointerUnion.h"
     24 #include "llvm/ADT/SmallVector.h"
     25 #include "llvm/ADT/StringMap.h"
     26 #include "llvm/ADT/StringRef.h"
     27 #include "llvm/Support/Allocator.h"
     28 #include "llvm/Support/ErrorOr.h"
     29 #include "llvm/Support/FileSystem.h"
     30 #include "llvm/Support/VirtualFileSystem.h"
     31 #include <ctime>
     32 #include <map>
     33 #include <memory>
     34 #include <string>
     35 
     36 namespace llvm {
     37 
     38 class MemoryBuffer;
     39 
     40 } // end namespace llvm
     41 
     42 namespace clang {
     43 
     44 class FileSystemStatCache;
     45 
     46 /// Implements support for file system lookup, file system caching,
     47 /// and directory search management.
     48 ///
     49 /// This also handles more advanced properties, such as uniquing files based
     50 /// on "inode", so that a file with two names (e.g. symlinked) will be treated
     51 /// as a single file.
     52 ///
     53 class FileManager : public RefCountedBase<FileManager> {
     54   IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
     55   FileSystemOptions FileSystemOpts;
     56 
     57   /// Cache for existing real directories.
     58   std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueRealDirs;
     59 
     60   /// Cache for existing real files.
     61   std::map<llvm::sys::fs::UniqueID, FileEntry> UniqueRealFiles;
     62 
     63   /// The virtual directories that we have allocated.
     64   ///
     65   /// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
     66   /// directories (foo/ and foo/bar/) here.
     67   SmallVector<std::unique_ptr<DirectoryEntry>, 4> VirtualDirectoryEntries;
     68   /// The virtual files that we have allocated.
     69   SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
     70 
     71   /// A set of files that bypass the maps and uniquing.  They can have
     72   /// conflicting filenames.
     73   SmallVector<std::unique_ptr<FileEntry>, 0> BypassFileEntries;
     74 
     75   /// A cache that maps paths to directory entries (either real or
     76   /// virtual) we have looked up, or an error that occurred when we looked up
     77   /// the directory.
     78   ///
     79   /// The actual Entries for real directories/files are
     80   /// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries
     81   /// for virtual directories/files are owned by
     82   /// VirtualDirectoryEntries/VirtualFileEntries above.
     83   ///
     84   llvm::StringMap<llvm::ErrorOr<DirectoryEntry &>, llvm::BumpPtrAllocator>
     85   SeenDirEntries;
     86 
     87   /// A cache that maps paths to file entries (either real or
     88   /// virtual) we have looked up, or an error that occurred when we looked up
     89   /// the file.
     90   ///
     91   /// \see SeenDirEntries
     92   llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>, llvm::BumpPtrAllocator>
     93       SeenFileEntries;
     94 
     95   /// A mirror of SeenFileEntries to give fake answers for getBypassFile().
     96   ///
     97   /// Don't bother hooking up a BumpPtrAllocator. This should be rarely used,
     98   /// and only on error paths.
     99   std::unique_ptr<llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>>>
    100       SeenBypassFileEntries;
    101 
    102   /// The file entry for stdin, if it has been accessed through the FileManager.
    103   Optional<FileEntryRef> STDIN;
    104 
    105   /// The canonical names of files and directories .
    106   llvm::DenseMap<const void *, llvm::StringRef> CanonicalNames;
    107 
    108   /// Storage for canonical names that we have computed.
    109   llvm::BumpPtrAllocator CanonicalNameStorage;
    110 
    111   /// Each FileEntry we create is assigned a unique ID #.
    112   ///
    113   unsigned NextFileUID;
    114 
    115   // Caching.
    116   std::unique_ptr<FileSystemStatCache> StatCache;
    117 
    118   std::error_code getStatValue(StringRef Path, llvm::vfs::Status &Status,
    119                                bool isFile,
    120                                std::unique_ptr<llvm::vfs::File> *F);
    121 
    122   /// Add all ancestors of the given path (pointing to either a file
    123   /// or a directory) as virtual directories.
    124   void addAncestorsAsVirtualDirs(StringRef Path);
    125 
    126   /// Fills the RealPathName in file entry.
    127   void fillRealPathName(FileEntry *UFE, llvm::StringRef FileName);
    128 
    129 public:
    130   /// Construct a file manager, optionally with a custom VFS.
    131   ///
    132   /// \param FS if non-null, the VFS to use.  Otherwise uses
    133   /// llvm::vfs::getRealFileSystem().
    134   FileManager(const FileSystemOptions &FileSystemOpts,
    135               IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = nullptr);
    136   ~FileManager();
    137 
    138   /// Installs the provided FileSystemStatCache object within
    139   /// the FileManager.
    140   ///
    141   /// Ownership of this object is transferred to the FileManager.
    142   ///
    143   /// \param statCache the new stat cache to install. Ownership of this
    144   /// object is transferred to the FileManager.
    145   void setStatCache(std::unique_ptr<FileSystemStatCache> statCache);
    146 
    147   /// Removes the FileSystemStatCache object from the manager.
    148   void clearStatCache();
    149 
    150   /// Returns the number of unique real file entries cached by the file manager.
    151   size_t getNumUniqueRealFiles() const { return UniqueRealFiles.size(); }
    152 
    153   /// Lookup, cache, and verify the specified directory (real or
    154   /// virtual).
    155   ///
    156   /// This returns a \c std::error_code if there was an error reading the
    157   /// directory. On success, returns the reference to the directory entry
    158   /// together with the exact path that was used to access a file by a
    159   /// particular call to getDirectoryRef.
    160   ///
    161   /// \param CacheFailure If true and the file does not exist, we'll cache
    162   /// the failure to find this file.
    163   llvm::Expected<DirectoryEntryRef> getDirectoryRef(StringRef DirName,
    164                                                     bool CacheFailure = true);
    165 
    166   /// Get a \c DirectoryEntryRef if it exists, without doing anything on error.
    167   llvm::Optional<DirectoryEntryRef>
    168   getOptionalDirectoryRef(StringRef DirName, bool CacheFailure = true) {
    169     return llvm::expectedToOptional(getDirectoryRef(DirName, CacheFailure));
    170   }
    171 
    172   /// Lookup, cache, and verify the specified directory (real or
    173   /// virtual).
    174   ///
    175   /// This function is deprecated and will be removed at some point in the
    176   /// future, new clients should use
    177   ///  \c getDirectoryRef.
    178   ///
    179   /// This returns a \c std::error_code if there was an error reading the
    180   /// directory. If there is no error, the DirectoryEntry is guaranteed to be
    181   /// non-NULL.
    182   ///
    183   /// \param CacheFailure If true and the file does not exist, we'll cache
    184   /// the failure to find this file.
    185   llvm::ErrorOr<const DirectoryEntry *>
    186   getDirectory(StringRef DirName, bool CacheFailure = true);
    187 
    188   /// Lookup, cache, and verify the specified file (real or
    189   /// virtual).
    190   ///
    191   /// This function is deprecated and will be removed at some point in the
    192   /// future, new clients should use
    193   ///  \c getFileRef.
    194   ///
    195   /// This returns a \c std::error_code if there was an error loading the file.
    196   /// If there is no error, the FileEntry is guaranteed to be non-NULL.
    197   ///
    198   /// \param OpenFile if true and the file exists, it will be opened.
    199   ///
    200   /// \param CacheFailure If true and the file does not exist, we'll cache
    201   /// the failure to find this file.
    202   llvm::ErrorOr<const FileEntry *>
    203   getFile(StringRef Filename, bool OpenFile = false, bool CacheFailure = true);
    204 
    205   /// Lookup, cache, and verify the specified file (real or virtual). Return the
    206   /// reference to the file entry together with the exact path that was used to
    207   /// access a file by a particular call to getFileRef. If the underlying VFS is
    208   /// a redirecting VFS that uses external file names, the returned FileEntryRef
    209   /// will use the external name instead of the filename that was passed to this
    210   /// method.
    211   ///
    212   /// This returns a \c std::error_code if there was an error loading the file,
    213   /// or a \c FileEntryRef otherwise.
    214   ///
    215   /// \param OpenFile if true and the file exists, it will be opened.
    216   ///
    217   /// \param CacheFailure If true and the file does not exist, we'll cache
    218   /// the failure to find this file.
    219   llvm::Expected<FileEntryRef> getFileRef(StringRef Filename,
    220                                           bool OpenFile = false,
    221                                           bool CacheFailure = true);
    222 
    223   /// Get the FileEntryRef for stdin, returning an error if stdin cannot be
    224   /// read.
    225   ///
    226   /// This reads and caches stdin before returning. Subsequent calls return the
    227   /// same file entry, and a reference to the cached input is returned by calls
    228   /// to getBufferForFile.
    229   llvm::Expected<FileEntryRef> getSTDIN();
    230 
    231   /// Get a FileEntryRef if it exists, without doing anything on error.
    232   llvm::Optional<FileEntryRef> getOptionalFileRef(StringRef Filename,
    233                                                   bool OpenFile = false,
    234                                                   bool CacheFailure = true) {
    235     return llvm::expectedToOptional(
    236         getFileRef(Filename, OpenFile, CacheFailure));
    237   }
    238 
    239   /// Returns the current file system options
    240   FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
    241   const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
    242 
    243   llvm::vfs::FileSystem &getVirtualFileSystem() const { return *FS; }
    244 
    245   void setVirtualFileSystem(IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
    246     this->FS = std::move(FS);
    247   }
    248 
    249   /// Retrieve a file entry for a "virtual" file that acts as
    250   /// if there were a file with the given name on disk.
    251   ///
    252   /// The file itself is not accessed.
    253   FileEntryRef getVirtualFileRef(StringRef Filename, off_t Size,
    254                                  time_t ModificationTime);
    255 
    256   const FileEntry *getVirtualFile(StringRef Filename, off_t Size,
    257                                   time_t ModificationTime);
    258 
    259   /// Retrieve a FileEntry that bypasses VFE, which is expected to be a virtual
    260   /// file entry, to access the real file.  The returned FileEntry will have
    261   /// the same filename as FE but a different identity and its own stat.
    262   ///
    263   /// This should be used only for rare error recovery paths because it
    264   /// bypasses all mapping and uniquing, blindly creating a new FileEntry.
    265   /// There is no attempt to deduplicate these; if you bypass the same file
    266   /// twice, you get two new file entries.
    267   llvm::Optional<FileEntryRef> getBypassFile(FileEntryRef VFE);
    268 
    269   /// Open the specified file as a MemoryBuffer, returning a new
    270   /// MemoryBuffer if successful, otherwise returning null.
    271   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
    272   getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
    273                    bool RequiresNullTerminator = true);
    274   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
    275   getBufferForFile(StringRef Filename, bool isVolatile = false,
    276                    bool RequiresNullTerminator = true) {
    277     return getBufferForFileImpl(Filename, /*FileSize=*/-1, isVolatile,
    278                                 RequiresNullTerminator);
    279   }
    280 
    281 private:
    282   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
    283   getBufferForFileImpl(StringRef Filename, int64_t FileSize, bool isVolatile,
    284                        bool RequiresNullTerminator);
    285 
    286 public:
    287   /// Get the 'stat' information for the given \p Path.
    288   ///
    289   /// If the path is relative, it will be resolved against the WorkingDir of the
    290   /// FileManager's FileSystemOptions.
    291   ///
    292   /// \returns a \c std::error_code describing an error, if there was one
    293   std::error_code getNoncachedStatValue(StringRef Path,
    294                                         llvm::vfs::Status &Result);
    295 
    296   /// If path is not absolute and FileSystemOptions set the working
    297   /// directory, the path is modified to be relative to the given
    298   /// working directory.
    299   /// \returns true if \c path changed.
    300   bool FixupRelativePath(SmallVectorImpl<char> &path) const;
    301 
    302   /// Makes \c Path absolute taking into account FileSystemOptions and the
    303   /// working directory option.
    304   /// \returns true if \c Path changed to absolute.
    305   bool makeAbsolutePath(SmallVectorImpl<char> &Path) const;
    306 
    307   /// Produce an array mapping from the unique IDs assigned to each
    308   /// file to the corresponding FileEntry pointer.
    309   void GetUniqueIDMapping(
    310                     SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
    311 
    312   /// Retrieve the canonical name for a given directory.
    313   ///
    314   /// This is a very expensive operation, despite its results being cached,
    315   /// and should only be used when the physical layout of the file system is
    316   /// required, which is (almost) never.
    317   StringRef getCanonicalName(const DirectoryEntry *Dir);
    318 
    319   /// Retrieve the canonical name for a given file.
    320   ///
    321   /// This is a very expensive operation, despite its results being cached,
    322   /// and should only be used when the physical layout of the file system is
    323   /// required, which is (almost) never.
    324   StringRef getCanonicalName(const FileEntry *File);
    325 
    326   void PrintStats() const;
    327 };
    328 
    329 } // end namespace clang
    330 
    331 #endif // LLVM_CLANG_BASIC_FILEMANAGER_H
    332