summaryrefslogtreecommitdiff
path: root/clang-r353983e/include/clang/Basic/FileManager.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang-r353983e/include/clang/Basic/FileManager.h')
-rw-r--r--clang-r353983e/include/clang/Basic/FileManager.h287
1 files changed, 287 insertions, 0 deletions
diff --git a/clang-r353983e/include/clang/Basic/FileManager.h b/clang-r353983e/include/clang/Basic/FileManager.h
new file mode 100644
index 00000000..88c1467b
--- /dev/null
+++ b/clang-r353983e/include/clang/Basic/FileManager.h
@@ -0,0 +1,287 @@
+//===--- FileManager.h - File System Probing and Caching --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Defines the clang::FileManager interface and associated types.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_FILEMANAGER_H
+#define LLVM_CLANG_BASIC_FILEMANAGER_H
+
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include <ctime>
+#include <map>
+#include <memory>
+#include <string>
+
+namespace llvm {
+
+class MemoryBuffer;
+
+} // end namespace llvm
+
+namespace clang {
+
+class FileSystemStatCache;
+
+/// Cached information about one directory (either on disk or in
+/// the virtual file system).
+class DirectoryEntry {
+ friend class FileManager;
+
+ StringRef Name; // Name of the directory.
+
+public:
+ StringRef getName() const { return Name; }
+};
+
+/// Cached information about one file (either on disk
+/// or in the virtual file system).
+///
+/// If the 'File' member is valid, then this FileEntry has an open file
+/// descriptor for the file.
+class FileEntry {
+ friend class FileManager;
+
+ StringRef Name; // Name of the file.
+ std::string RealPathName; // Real path to the file; could be empty.
+ off_t Size; // File size in bytes.
+ time_t ModTime; // Modification time of file.
+ const DirectoryEntry *Dir; // Directory file lives in.
+ unsigned UID; // A unique (small) ID for the file.
+ llvm::sys::fs::UniqueID UniqueID;
+ bool IsNamedPipe;
+ bool InPCH;
+ bool IsValid; // Is this \c FileEntry initialized and valid?
+
+ /// The open file, if it is owned by the \p FileEntry.
+ mutable std::unique_ptr<llvm::vfs::File> File;
+
+public:
+ FileEntry()
+ : UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false)
+ {}
+
+ FileEntry(const FileEntry &) = delete;
+ FileEntry &operator=(const FileEntry &) = delete;
+
+ StringRef getName() const { return Name; }
+ StringRef tryGetRealPathName() const { return RealPathName; }
+ bool isValid() const { return IsValid; }
+ off_t getSize() const { return Size; }
+ unsigned getUID() const { return UID; }
+ const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
+ bool isInPCH() const { return InPCH; }
+ time_t getModificationTime() const { return ModTime; }
+
+ /// Return the directory the file lives in.
+ const DirectoryEntry *getDir() const { return Dir; }
+
+ bool operator<(const FileEntry &RHS) const { return UniqueID < RHS.UniqueID; }
+
+ /// Check whether the file is a named pipe (and thus can't be opened by
+ /// the native FileManager methods).
+ bool isNamedPipe() const { return IsNamedPipe; }
+
+ void closeFile() const {
+ File.reset(); // rely on destructor to close File
+ }
+
+ // Only for use in tests to see if deferred opens are happening, rather than
+ // relying on RealPathName being empty.
+ bool isOpenForTests() const { return File != nullptr; }
+};
+
+struct FileData;
+
+/// Implements support for file system lookup, file system caching,
+/// and directory search management.
+///
+/// This also handles more advanced properties, such as uniquing files based
+/// on "inode", so that a file with two names (e.g. symlinked) will be treated
+/// as a single file.
+///
+class FileManager : public RefCountedBase<FileManager> {
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
+ FileSystemOptions FileSystemOpts;
+
+ /// Cache for existing real directories.
+ std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueRealDirs;
+
+ /// Cache for existing real files.
+ std::map<llvm::sys::fs::UniqueID, FileEntry> UniqueRealFiles;
+
+ /// The virtual directories that we have allocated.
+ ///
+ /// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
+ /// directories (foo/ and foo/bar/) here.
+ SmallVector<std::unique_ptr<DirectoryEntry>, 4> VirtualDirectoryEntries;
+ /// The virtual files that we have allocated.
+ SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
+
+ /// A cache that maps paths to directory entries (either real or
+ /// virtual) we have looked up
+ ///
+ /// The actual Entries for real directories/files are
+ /// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries
+ /// for virtual directories/files are owned by
+ /// VirtualDirectoryEntries/VirtualFileEntries above.
+ ///
+ llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries;
+
+ /// A cache that maps paths to file entries (either real or
+ /// virtual) we have looked up.
+ ///
+ /// \see SeenDirEntries
+ llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries;
+
+ /// The canonical names of directories.
+ llvm::DenseMap<const DirectoryEntry *, llvm::StringRef> CanonicalDirNames;
+
+ /// Storage for canonical names that we have computed.
+ llvm::BumpPtrAllocator CanonicalNameStorage;
+
+ /// Each FileEntry we create is assigned a unique ID #.
+ ///
+ unsigned NextFileUID;
+
+ // Statistics.
+ unsigned NumDirLookups, NumFileLookups;
+ unsigned NumDirCacheMisses, NumFileCacheMisses;
+
+ // Caching.
+ std::unique_ptr<FileSystemStatCache> StatCache;
+
+ bool getStatValue(StringRef Path, FileData &Data, bool isFile,
+ std::unique_ptr<llvm::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);
+
+ /// Fills the RealPathName in file entry.
+ void fillRealPathName(FileEntry *UFE, llvm::StringRef FileName);
+
+public:
+ FileManager(const FileSystemOptions &FileSystemOpts,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = nullptr);
+ ~FileManager();
+
+ /// Installs the provided FileSystemStatCache object within
+ /// the FileManager.
+ ///
+ /// Ownership of this object is transferred to the FileManager.
+ ///
+ /// \param statCache the new stat cache to install. Ownership of this
+ /// object is transferred to the FileManager.
+ void setStatCache(std::unique_ptr<FileSystemStatCache> statCache);
+
+ /// Removes the FileSystemStatCache object from the manager.
+ void clearStatCache();
+
+ /// Lookup, cache, and verify the specified directory (real or
+ /// virtual).
+ ///
+ /// This returns NULL if the directory doesn't exist.
+ ///
+ /// \param CacheFailure If true and the file does not exist, we'll cache
+ /// the failure to find this file.
+ const DirectoryEntry *getDirectory(StringRef DirName,
+ bool CacheFailure = true);
+
+ /// Lookup, cache, and verify the specified file (real or
+ /// virtual).
+ ///
+ /// This returns NULL if the file doesn't exist.
+ ///
+ /// \param OpenFile if true and the file exists, it will be opened.
+ ///
+ /// \param CacheFailure If true and the file does not exist, we'll cache
+ /// the failure to find this file.
+ const FileEntry *getFile(StringRef Filename, bool OpenFile = false,
+ bool CacheFailure = true);
+
+ /// Returns the current file system options
+ FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
+
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> getVirtualFileSystem() const {
+ return FS;
+ }
+
+ /// Retrieve a file entry for a "virtual" file that acts as
+ /// if there were a file with the given name on disk.
+ ///
+ /// The file itself is not accessed.
+ const FileEntry *getVirtualFile(StringRef Filename, off_t Size,
+ time_t ModificationTime);
+
+ /// Open the specified file as a MemoryBuffer, returning a new
+ /// MemoryBuffer if successful, otherwise returning null.
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
+ bool ShouldCloseOpenFile = true);
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBufferForFile(StringRef Filename, bool isVolatile = false);
+
+ /// Get the 'stat' information for the given \p Path.
+ ///
+ /// If the path is relative, it will be resolved against the WorkingDir of the
+ /// FileManager's FileSystemOptions.
+ ///
+ /// \returns false on success, true on error.
+ bool getNoncachedStatValue(StringRef Path, llvm::vfs::Status &Result);
+
+ /// Remove the real file \p Entry from the cache.
+ void invalidateCache(const FileEntry *Entry);
+
+ /// If path is not absolute and FileSystemOptions set the working
+ /// directory, the path is modified to be relative to the given
+ /// working directory.
+ /// \returns true if \c path changed.
+ bool FixupRelativePath(SmallVectorImpl<char> &path) const;
+
+ /// Makes \c Path absolute taking into account FileSystemOptions and the
+ /// working directory option.
+ /// \returns true if \c Path changed to absolute.
+ bool makeAbsolutePath(SmallVectorImpl<char> &Path) const;
+
+ /// Produce an array mapping from the unique IDs assigned to each
+ /// file to the corresponding FileEntry pointer.
+ void GetUniqueIDMapping(
+ SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
+
+ /// Modifies the size and modification time of a previously created
+ /// FileEntry. Use with caution.
+ static void modifyFileEntry(FileEntry *File, off_t Size,
+ time_t ModificationTime);
+
+ /// Retrieve the canonical name for a given directory.
+ ///
+ /// This is a very expensive operation, despite its results being cached,
+ /// and should only be used when the physical layout of the file system is
+ /// required, which is (almost) never.
+ StringRef getCanonicalName(const DirectoryEntry *Dir);
+
+ void PrintStats() const;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_FILEMANAGER_H