clang 22.0.0git
FileManager.h
Go to the documentation of this file.
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
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
36namespace llvm {
37
38class MemoryBuffer;
39
40} // end namespace llvm
41
42namespace clang {
43
44class 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///
53class FileManager : public RefCountedBase<FileManager> {
55 FileSystemOptions FileSystemOpts;
56 llvm::SpecificBumpPtrAllocator<FileEntry> FilesAlloc;
57 llvm::SpecificBumpPtrAllocator<DirectoryEntry> DirsAlloc;
58
59 /// Cache for existing real directories.
60 llvm::DenseMap<llvm::sys::fs::UniqueID, DirectoryEntry *> UniqueRealDirs;
61
62 /// Cache for existing real files.
63 llvm::DenseMap<llvm::sys::fs::UniqueID, FileEntry *> UniqueRealFiles;
64
65 /// The virtual directories that we have allocated.
66 ///
67 /// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
68 /// directories (foo/ and foo/bar/) here.
69 SmallVector<DirectoryEntry *, 4> VirtualDirectoryEntries;
70 /// The virtual files that we have allocated.
71 SmallVector<FileEntry *, 4> VirtualFileEntries;
72
73 /// A set of files that bypass the maps and uniquing. They can have
74 /// conflicting filenames.
75 SmallVector<FileEntry *, 0> BypassFileEntries;
76
77 /// A cache that maps paths to directory entries (either real or
78 /// virtual) we have looked up, or an error that occurred when we looked up
79 /// the directory.
80 ///
81 /// The actual Entries for real directories/files are
82 /// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries
83 /// for virtual directories/files are owned by
84 /// VirtualDirectoryEntries/VirtualFileEntries above.
85 ///
86 llvm::StringMap<llvm::ErrorOr<DirectoryEntry &>, llvm::BumpPtrAllocator>
87 SeenDirEntries;
88
89 /// A cache that maps paths to file entries (either real or
90 /// virtual) we have looked up, or an error that occurred when we looked up
91 /// the file.
92 ///
93 /// \see SeenDirEntries
94 llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>, llvm::BumpPtrAllocator>
95 SeenFileEntries;
96
97 /// A mirror of SeenFileEntries to give fake answers for getBypassFile().
98 ///
99 /// Don't bother hooking up a BumpPtrAllocator. This should be rarely used,
100 /// and only on error paths.
101 std::unique_ptr<llvm::StringMap<llvm::ErrorOr<FileEntryRef::MapValue>>>
102 SeenBypassFileEntries;
103
104 /// The file entry for stdin, if it has been accessed through the FileManager.
106
107 /// The canonical names of files and directories .
108 llvm::DenseMap<const void *, llvm::StringRef> CanonicalNames;
109
110 /// Storage for canonical names that we have computed.
111 llvm::BumpPtrAllocator CanonicalNameStorage;
112
113 /// Each FileEntry we create is assigned a unique ID #.
114 ///
115 unsigned NextFileUID;
116
117 /// Statistics gathered during the lifetime of the FileManager.
118 unsigned NumDirLookups = 0;
119 unsigned NumFileLookups = 0;
120 unsigned NumDirCacheMisses = 0;
121 unsigned NumFileCacheMisses = 0;
122
123 // Caching.
124 std::unique_ptr<FileSystemStatCache> StatCache;
125
126 std::error_code getStatValue(StringRef Path, llvm::vfs::Status &Status,
127 bool isFile, std::unique_ptr<llvm::vfs::File> *F,
128 bool IsText = true);
129
130 /// Add all ancestors of the given path (pointing to either a file
131 /// or a directory) as virtual directories.
132 void addAncestorsAsVirtualDirs(StringRef Path);
133
134 /// Fills the RealPathName in file entry.
135 void fillRealPathName(FileEntry *UFE, llvm::StringRef FileName);
136
137public:
138 /// Construct a file manager, optionally with a custom VFS.
139 ///
140 /// \param FS if non-null, the VFS to use. Otherwise uses
141 /// llvm::vfs::getRealFileSystem().
142 FileManager(const FileSystemOptions &FileSystemOpts,
145
146 /// Installs the provided FileSystemStatCache object within
147 /// the FileManager.
148 ///
149 /// Ownership of this object is transferred to the FileManager.
150 ///
151 /// \param statCache the new stat cache to install. Ownership of this
152 /// object is transferred to the FileManager.
153 void setStatCache(std::unique_ptr<FileSystemStatCache> statCache);
154
155 /// Removes the FileSystemStatCache object from the manager.
156 void clearStatCache();
157
158 /// Returns the number of unique real file entries cached by the file manager.
159 size_t getNumUniqueRealFiles() const { return UniqueRealFiles.size(); }
160
161 /// Lookup, cache, and verify the specified directory (real or
162 /// virtual).
163 ///
164 /// This returns a \c std::error_code if there was an error reading the
165 /// directory. On success, returns the reference to the directory entry
166 /// together with the exact path that was used to access a file by a
167 /// particular call to getDirectoryRef.
168 ///
169 /// \param CacheFailure If true and the file does not exist, we'll cache
170 /// the failure to find this file.
172 bool CacheFailure = true);
173
174 /// Get a \c DirectoryEntryRef if it exists, without doing anything on error.
176 bool CacheFailure = true) {
177 return llvm::expectedToOptional(getDirectoryRef(DirName, CacheFailure));
178 }
179
180 /// Lookup, cache, and verify the specified file (real or virtual). Return the
181 /// reference to the file entry together with the exact path that was used to
182 /// access a file by a particular call to getFileRef. If the underlying VFS is
183 /// a redirecting VFS that uses external file names, the returned FileEntryRef
184 /// will use the external name instead of the filename that was passed to this
185 /// method.
186 ///
187 /// This returns a \c std::error_code if there was an error loading the file,
188 /// or a \c FileEntryRef otherwise.
189 ///
190 /// \param OpenFile if true and the file exists, it will be opened.
191 ///
192 /// \param CacheFailure If true and the file does not exist, we'll cache
193 /// the failure to find this file.
195 bool OpenFile = false,
196 bool CacheFailure = true,
197 bool IsText = true);
198
199 /// Get the FileEntryRef for stdin, returning an error if stdin cannot be
200 /// read.
201 ///
202 /// This reads and caches stdin before returning. Subsequent calls return the
203 /// same file entry, and a reference to the cached input is returned by calls
204 /// to getBufferForFile.
206
207 /// Get a FileEntryRef if it exists, without doing anything on error.
209 bool OpenFile = false,
210 bool CacheFailure = true) {
211 return llvm::expectedToOptional(
212 getFileRef(Filename, OpenFile, CacheFailure));
213 }
214
215 /// Returns the current file system options
216 FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
217 const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
218
219 llvm::vfs::FileSystem &getVirtualFileSystem() const { return *FS; }
222 return FS;
223 }
224
225 /// Enable or disable tracking of VFS usage. Used to not track full header
226 /// search and implicit modulemap lookup.
227 void trackVFSUsage(bool Active);
228
230 this->FS = std::move(FS);
231 }
232
233 /// Retrieve a file entry for a "virtual" file that acts as
234 /// if there were a file with the given name on disk.
235 ///
236 /// The file itself is not accessed.
237 FileEntryRef getVirtualFileRef(StringRef Filename, off_t Size,
238 time_t ModificationTime);
239
240 /// Retrieve a FileEntry that bypasses VFE, which is expected to be a virtual
241 /// file entry, to access the real file. The returned FileEntry will have
242 /// the same filename as FE but a different identity and its own stat.
243 ///
244 /// This should be used only for rare error recovery paths because it
245 /// bypasses all mapping and uniquing, blindly creating a new FileEntry.
246 /// There is no attempt to deduplicate these; if you bypass the same file
247 /// twice, you get two new file entries.
249
250 /// Open the specified file as a MemoryBuffer, returning a new
251 /// MemoryBuffer if successful, otherwise returning null.
252 /// The IsText parameter controls whether the file should be opened as a text
253 /// or binary file, and should be set to false if the file contents should be
254 /// treated as binary.
255 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
256 getBufferForFile(FileEntryRef Entry, bool isVolatile = false,
257 bool RequiresNullTerminator = true,
258 std::optional<int64_t> MaybeLimit = std::nullopt,
259 bool IsText = true);
260 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
261 getBufferForFile(StringRef Filename, bool isVolatile = false,
262 bool RequiresNullTerminator = true,
263 std::optional<int64_t> MaybeLimit = std::nullopt,
264 bool IsText = true) const {
265 return getBufferForFileImpl(Filename,
266 /*FileSize=*/MaybeLimit.value_or(-1),
267 isVolatile, RequiresNullTerminator, IsText);
268 }
269
270private:
271 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
272 getBufferForFileImpl(StringRef Filename, int64_t FileSize, bool isVolatile,
273 bool RequiresNullTerminator, bool IsText) const;
274
275 DirectoryEntry *&getRealDirEntry(const llvm::vfs::Status &Status);
276
277public:
278 /// Get the 'stat' information for the given \p Path.
279 ///
280 /// If the path is relative, it will be resolved against the WorkingDir of the
281 /// FileManager's FileSystemOptions.
282 ///
283 /// \returns a \c std::error_code describing an error, if there was one
284 std::error_code getNoncachedStatValue(StringRef Path,
285 llvm::vfs::Status &Result);
286
287 /// If path is not absolute and FileSystemOptions set the working
288 /// directory, the path is modified to be relative to the given
289 /// working directory.
290 /// \returns true if \c path changed.
292
293 /// Makes \c Path absolute taking into account FileSystemOptions and the
294 /// working directory option.
295 /// \returns true if \c Path changed to absolute.
297
298 /// Produce an array mapping from the unique IDs assigned to each
299 /// file to the corresponding FileEntryRef.
300 void
302
303 /// Retrieve the canonical name for a given directory.
304 ///
305 /// This is a very expensive operation, despite its results being cached,
306 /// and should only be used when the physical layout of the file system is
307 /// required, which is (almost) never.
308 StringRef getCanonicalName(DirectoryEntryRef Dir);
309
310 /// Retrieve the canonical name for a given file.
311 ///
312 /// This is a very expensive operation, despite its results being cached,
313 /// and should only be used when the physical layout of the file system is
314 /// required, which is (almost) never.
316
317private:
318 /// Retrieve the canonical name for a given file or directory.
319 ///
320 /// The first param is a key in the CanonicalNames array.
321 StringRef getCanonicalName(const void *Entry, StringRef Name);
322
323public:
324 void PrintStats() const;
325
326 /// Import statistics from a child FileManager and add them to this current
327 /// FileManager.
328 void AddStats(const FileManager &Other);
329};
330
331} // end namespace clang
332
333#endif // LLVM_CLANG_BASIC_FILEMANAGER_H
IndirectLocalPath & Path
Defines interfaces for clang::DirectoryEntry and clang::DirectoryEntryRef.
Defines interfaces for clang::FileEntry and clang::FileEntryRef.
Defines the clang::FileSystemOptions interface.
StringRef Filename
Definition: Format.cpp:3177
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
Cached information about one directory (either on disk or in the virtual file system).
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Definition: FileEntry.h:57
Cached information about one file (either on disk or in the virtual file system).
Definition: FileEntry.h:306
Implements support for file system lookup, file system caching, and directory search management.
Definition: FileManager.h:53
void AddStats(const FileManager &Other)
Import statistics from a child FileManager and add them to this current FileManager.
void trackVFSUsage(bool Active)
Enable or disable tracking of VFS usage.
void clearStatCache()
Removes the FileSystemStatCache object from the manager.
Definition: FileManager.cpp:61
llvm::vfs::FileSystem & getVirtualFileSystem() const
Definition: FileManager.h:219
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt, bool IsText=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
std::error_code getNoncachedStatValue(StringRef Path, llvm::vfs::Status &Result)
Get the 'stat' information for the given Path.
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
Definition: FileManager.h:208
llvm::Expected< FileEntryRef > getSTDIN()
Get the FileEntryRef for stdin, returning an error if stdin cannot be read.
StringRef getCanonicalName(DirectoryEntryRef Dir)
Retrieve the canonical name for a given directory.
void GetUniqueIDMapping(SmallVectorImpl< OptionalFileEntryRef > &UIDToFiles) const
Produce an array mapping from the unique IDs assigned to each file to the corresponding FileEntryRef.
bool makeAbsolutePath(SmallVectorImpl< char > &Path) const
Makes Path absolute taking into account FileSystemOptions and the working directory option.
llvm::Expected< DirectoryEntryRef > getDirectoryRef(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
void setStatCache(std::unique_ptr< FileSystemStatCache > statCache)
Installs the provided FileSystemStatCache object within the FileManager.
Definition: FileManager.cpp:56
FileSystemOptions & getFileSystemOpts()
Returns the current file system options.
Definition: FileManager.h:216
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > getVirtualFileSystemPtr() const
Definition: FileManager.h:221
const FileSystemOptions & getFileSystemOpts() const
Definition: FileManager.h:217
FileEntryRef getVirtualFileRef(StringRef Filename, off_t Size, time_t ModificationTime)
Retrieve a file entry for a "virtual" file that acts as if there were a file with the given name on d...
size_t getNumUniqueRealFiles() const
Returns the number of unique real file entries cached by the file manager.
Definition: FileManager.h:159
bool FixupRelativePath(SmallVectorImpl< char > &path) const
If path is not absolute and FileSystemOptions set the working directory, the path is modified to be r...
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(StringRef Filename, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt, bool IsText=true) const
Definition: FileManager.h:261
void PrintStats() const
OptionalFileEntryRef getBypassFile(FileEntryRef VFE)
Retrieve a FileEntry that bypasses VFE, which is expected to be a virtual file entry,...
void setVirtualFileSystem(IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
Definition: FileManager.h:229
OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)
Get a DirectoryEntryRef if it exists, without doing anything on error.
Definition: FileManager.h:175
llvm::Expected< FileEntryRef > getFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Lookup, cache, and verify the specified file (real or virtual).
Keeps track of options that affect how file operations are performed.
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
@ Other
Other implicit parameter.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30