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