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