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