clang 20.0.0git
FileEntry.h
Go to the documentation of this file.
1//===- clang/Basic/FileEntry.h - File references ----------------*- 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 interfaces for clang::FileEntry and clang::FileEntryRef.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_BASIC_FILEENTRY_H
15#define LLVM_CLANG_BASIC_FILEENTRY_H
16
19#include "clang/Basic/LLVM.h"
20#include "llvm/ADT/DenseMapInfo.h"
21#include "llvm/ADT/Hashing.h"
22#include "llvm/ADT/PointerUnion.h"
23#include "llvm/ADT/StringMap.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/Support/ErrorOr.h"
26#include "llvm/Support/FileSystem/UniqueID.h"
27
28#include <optional>
29#include <utility>
30
31namespace llvm {
32
33class MemoryBuffer;
34
35namespace vfs {
36
37class File;
38
39} // namespace vfs
40} // namespace llvm
41
42namespace clang {
43
44class FileEntryRef;
45
46namespace optional_detail {
47
48/// Forward declare a template specialization for OptionalStorage.
49template <> class OptionalStorage<clang::FileEntryRef>;
50
51} // namespace optional_detail
52
53class FileEntry;
54
55/// A reference to a \c FileEntry that includes the name of the file as it was
56/// accessed by the FileManager's client.
58public:
59 /// The name of this FileEntry. If a VFS uses 'use-external-name', this is
60 /// the redirected name. See getRequestedName().
61 StringRef getName() const { return getBaseMapEntry().first(); }
62
63 /// The name of this FileEntry, as originally requested without applying any
64 /// remappings for VFS 'use-external-name'.
65 ///
66 /// FIXME: this should be the semantics of getName(). See comment in
67 /// FileManager::getFileRef().
68 StringRef getNameAsRequested() const { return ME->first(); }
69
70 const FileEntry &getFileEntry() const {
71 return *cast<FileEntry *>(getBaseMapEntry().second->V);
72 }
73
74 // This function is used if the buffer size needs to be increased
75 // due to potential z/OS EBCDIC -> UTF-8 conversion
76 inline void updateFileEntryBufferSize(unsigned BufferSize);
77
78 DirectoryEntryRef getDir() const { return ME->second->Dir; }
79
80 inline off_t getSize() const;
81 inline unsigned getUID() const;
82 inline const llvm::sys::fs::UniqueID &getUniqueID() const;
83 inline time_t getModificationTime() const;
84 inline bool isNamedPipe() const;
85 inline void closeFile() const;
86
87 /// Check if the underlying FileEntry is the same, intentially ignoring
88 /// whether the file was referenced with the same spelling of the filename.
89 friend bool operator==(const FileEntryRef &LHS, const FileEntryRef &RHS) {
90 return &LHS.getFileEntry() == &RHS.getFileEntry();
91 }
92 friend bool operator==(const FileEntry *LHS, const FileEntryRef &RHS) {
93 return LHS == &RHS.getFileEntry();
94 }
95 friend bool operator==(const FileEntryRef &LHS, const FileEntry *RHS) {
96 return &LHS.getFileEntry() == RHS;
97 }
98 friend bool operator!=(const FileEntryRef &LHS, const FileEntryRef &RHS) {
99 return !(LHS == RHS);
100 }
101 friend bool operator!=(const FileEntry *LHS, const FileEntryRef &RHS) {
102 return !(LHS == RHS);
103 }
104 friend bool operator!=(const FileEntryRef &LHS, const FileEntry *RHS) {
105 return !(LHS == RHS);
106 }
107
108 /// Hash code is based on the FileEntry, not the specific named reference,
109 /// just like operator==.
110 friend llvm::hash_code hash_value(FileEntryRef Ref) {
111 return llvm::hash_value(&Ref.getFileEntry());
112 }
113
114 struct MapValue;
115
116 /// Type used in the StringMap.
117 using MapEntry = llvm::StringMapEntry<llvm::ErrorOr<MapValue>>;
118
119 /// Type stored in the StringMap.
120 struct MapValue {
121 /// The pointer at another MapEntry is used when the FileManager should
122 /// silently forward from one name to another, which occurs in Redirecting
123 /// VFSs that use external names. In that case, the \c FileEntryRef
124 /// returned by the \c FileManager will have the external name, and not the
125 /// name that was used to lookup the file.
126 llvm::PointerUnion<FileEntry *, const MapEntry *> V;
127
128 /// Directory the file was found in.
130
131 MapValue() = delete;
132 MapValue(FileEntry &FE, DirectoryEntryRef Dir) : V(&FE), Dir(Dir) {}
133 MapValue(MapEntry &ME, DirectoryEntryRef Dir) : V(&ME), Dir(Dir) {}
134 };
135
136 /// Check if RHS referenced the file in exactly the same way.
137 bool isSameRef(const FileEntryRef &RHS) const { return ME == RHS.ME; }
138
139 /// Allow FileEntryRef to degrade into 'const FileEntry*' to facilitate
140 /// incremental adoption.
141 ///
142 /// The goal is to avoid code churn due to dances like the following:
143 /// \code
144 /// // Old code.
145 /// lvalue = rvalue;
146 ///
147 /// // Temporary code from an incremental patch.
148 /// lvalue = &rvalue.getFileEntry();
149 ///
150 /// // Final code.
151 /// lvalue = rvalue;
152 /// \endcode
153 ///
154 /// FIXME: Once FileEntryRef is "everywhere" and FileEntry::LastRef and
155 /// FileEntry::getName have been deleted, delete this implicit conversion.
156 operator const FileEntry *() const { return &getFileEntry(); }
157
158 FileEntryRef() = delete;
159 explicit FileEntryRef(const MapEntry &ME) : ME(&ME) {
160 assert(ME.second && "Expected payload");
161 assert(ME.second->V && "Expected non-null");
162 }
163
164 /// Expose the underlying MapEntry to simplify packing in a PointerIntPair or
165 /// PointerUnion and allow construction in Optional.
166 const clang::FileEntryRef::MapEntry &getMapEntry() const { return *ME; }
167
168 /// Retrieve the base MapEntry after redirects.
169 const MapEntry &getBaseMapEntry() const {
170 const MapEntry *Base = ME;
171 while (const auto *Next = Base->second->V.dyn_cast<const MapEntry *>())
172 Base = Next;
173 return *Base;
174 }
175
176private:
178 struct optional_none_tag {};
179
180 // Private constructor for use by OptionalStorage.
181 FileEntryRef(optional_none_tag) : ME(nullptr) {}
182 bool hasOptionalValue() const { return ME; }
183
184 friend struct llvm::DenseMapInfo<FileEntryRef>;
185 struct dense_map_empty_tag {};
186 struct dense_map_tombstone_tag {};
187
188 // Private constructors for use by DenseMapInfo.
189 FileEntryRef(dense_map_empty_tag)
190 : ME(llvm::DenseMapInfo<const MapEntry *>::getEmptyKey()) {}
191 FileEntryRef(dense_map_tombstone_tag)
192 : ME(llvm::DenseMapInfo<const MapEntry *>::getTombstoneKey()) {}
193 bool isSpecialDenseMapKey() const {
194 return isSameRef(FileEntryRef(dense_map_empty_tag())) ||
195 isSameRef(FileEntryRef(dense_map_tombstone_tag()));
196 }
197
198 const MapEntry *ME;
199};
200
201static_assert(sizeof(FileEntryRef) == sizeof(const FileEntry *),
202 "FileEntryRef must avoid size overhead");
203
204static_assert(std::is_trivially_copyable<FileEntryRef>::value,
205 "FileEntryRef must be trivially copyable");
206
208
209namespace optional_detail {
210
211/// Customize OptionalStorage<FileEntryRef> to use FileEntryRef and its
212/// optional_none_tag to keep it the size of a single pointer.
213template <>
215 : public clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef> {
216 using StorageImpl =
218
219public:
220 OptionalStorage() = default;
221
222 template <class... ArgTypes>
223 explicit OptionalStorage(std::in_place_t, ArgTypes &&...Args)
224 : StorageImpl(std::in_place_t{}, std::forward<ArgTypes>(Args)...) {}
225
227 StorageImpl::operator=(Ref);
228 return *this;
229 }
230};
231
232static_assert(sizeof(OptionalFileEntryRef) == sizeof(FileEntryRef),
233 "OptionalFileEntryRef must avoid size overhead");
234
235static_assert(std::is_trivially_copyable<OptionalFileEntryRef>::value,
236 "OptionalFileEntryRef should be trivially copyable");
237
238} // end namespace optional_detail
239} // namespace clang
240
241namespace llvm {
242
243/// Specialisation of DenseMapInfo for FileEntryRef.
244template <> struct DenseMapInfo<clang::FileEntryRef> {
246 return clang::FileEntryRef(clang::FileEntryRef::dense_map_empty_tag());
247 }
248
250 return clang::FileEntryRef(clang::FileEntryRef::dense_map_tombstone_tag());
251 }
252
253 static unsigned getHashValue(clang::FileEntryRef Val) {
254 return hash_value(Val);
255 }
256
258 // Catch the easy cases: both empty, both tombstone, or the same ref.
259 if (LHS.isSameRef(RHS))
260 return true;
261
262 // Confirm LHS and RHS are valid.
263 if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey())
264 return false;
265
266 // It's safe to use operator==.
267 return LHS == RHS;
268 }
269
270 /// Support for finding `const FileEntry *` in a `DenseMap<FileEntryRef, T>`.
271 /// @{
272 static unsigned getHashValue(const clang::FileEntry *Val) {
273 return llvm::hash_value(Val);
274 }
275 static bool isEqual(const clang::FileEntry *LHS, clang::FileEntryRef RHS) {
276 if (RHS.isSpecialDenseMapKey())
277 return false;
278 return LHS == RHS;
279 }
280 /// @}
281};
282
283} // end namespace llvm
284
285namespace clang {
286
287inline bool operator==(const FileEntry *LHS, const OptionalFileEntryRef &RHS) {
288 return LHS == (RHS ? &RHS->getFileEntry() : nullptr);
289}
290inline bool operator==(const OptionalFileEntryRef &LHS, const FileEntry *RHS) {
291 return (LHS ? &LHS->getFileEntry() : nullptr) == RHS;
292}
293inline bool operator!=(const FileEntry *LHS, const OptionalFileEntryRef &RHS) {
294 return !(LHS == RHS);
295}
296inline bool operator!=(const OptionalFileEntryRef &LHS, const FileEntry *RHS) {
297 return !(LHS == RHS);
298}
299
300/// Cached information about one file (either on disk
301/// or in the virtual file system).
302///
303/// If the 'File' member is valid, then this FileEntry has an open file
304/// descriptor for the file.
306 friend class FileManager;
308 FileEntry();
309 FileEntry(const FileEntry &) = delete;
310 FileEntry &operator=(const FileEntry &) = delete;
311
312 std::string RealPathName; // Real path to the file; could be empty.
313 off_t Size = 0; // File size in bytes.
314 time_t ModTime = 0; // Modification time of file.
315 const DirectoryEntry *Dir = nullptr; // Directory file lives in.
316 llvm::sys::fs::UniqueID UniqueID;
317 unsigned UID = 0; // A unique (small) ID for the file.
318 bool IsNamedPipe = false;
319
320 /// The open file, if it is owned by the \p FileEntry.
321 mutable std::unique_ptr<llvm::vfs::File> File;
322
323 /// The file content, if it is owned by the \p FileEntry.
324 std::unique_ptr<llvm::MemoryBuffer> Content;
325
326public:
328
329 StringRef tryGetRealPathName() const { return RealPathName; }
330 off_t getSize() const { return Size; }
331 // Size may increase due to potential z/OS EBCDIC -> UTF-8 conversion.
332 void setSize(off_t NewSize) { Size = NewSize; }
333 unsigned getUID() const { return UID; }
334 const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
335 time_t getModificationTime() const { return ModTime; }
336
337 /// Return the directory the file lives in.
338 const DirectoryEntry *getDir() const { return Dir; }
339
340 /// Check whether the file is a named pipe (and thus can't be opened by
341 /// the native FileManager methods).
342 bool isNamedPipe() const { return IsNamedPipe; }
343
344 void closeFile() const;
345};
346
347off_t FileEntryRef::getSize() const { return getFileEntry().getSize(); }
348
349unsigned FileEntryRef::getUID() const { return getFileEntry().getUID(); }
350
351const llvm::sys::fs::UniqueID &FileEntryRef::getUniqueID() const {
352 return getFileEntry().getUniqueID();
353}
354
357}
358
360
362
364 cast<FileEntry *>(getBaseMapEntry().second->V)->setSize(BufferSize);
365}
366
367} // end namespace clang
368
369#endif // LLVM_CLANG_BASIC_FILEENTRY_H
#define V(N, I)
Definition: ASTContext.h:3443
Defines interfaces for clang::DirectoryEntry and clang::DirectoryEntryRef.
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
friend bool operator==(const FileEntry *LHS, const FileEntryRef &RHS)
Definition: FileEntry.h:92
friend llvm::hash_code hash_value(FileEntryRef Ref)
Hash code is based on the FileEntry, not the specific named reference, just like operator==.
Definition: FileEntry.h:110
const MapEntry & getBaseMapEntry() const
Retrieve the base MapEntry after redirects.
Definition: FileEntry.h:169
const FileEntry & getFileEntry() const
Definition: FileEntry.h:70
bool isSameRef(const FileEntryRef &RHS) const
Check if RHS referenced the file in exactly the same way.
Definition: FileEntry.h:137
const clang::FileEntryRef::MapEntry & getMapEntry() const
Expose the underlying MapEntry to simplify packing in a PointerIntPair or PointerUnion and allow cons...
Definition: FileEntry.h:166
void closeFile() const
Definition: FileEntry.h:361
time_t getModificationTime() const
Definition: FileEntry.h:355
friend bool operator!=(const FileEntryRef &LHS, const FileEntryRef &RHS)
Definition: FileEntry.h:98
bool isNamedPipe() const
Definition: FileEntry.h:359
void updateFileEntryBufferSize(unsigned BufferSize)
Definition: FileEntry.h:363
FileEntryRef(const MapEntry &ME)
Definition: FileEntry.h:159
friend bool operator!=(const FileEntry *LHS, const FileEntryRef &RHS)
Definition: FileEntry.h:101
off_t getSize() const
Definition: FileEntry.h:347
llvm::StringMapEntry< llvm::ErrorOr< MapValue > > MapEntry
Type used in the StringMap.
Definition: FileEntry.h:117
StringRef getName() const
The name of this FileEntry.
Definition: FileEntry.h:61
friend bool operator!=(const FileEntryRef &LHS, const FileEntry *RHS)
Definition: FileEntry.h:104
const llvm::sys::fs::UniqueID & getUniqueID() const
Definition: FileEntry.h:351
StringRef getNameAsRequested() const
The name of this FileEntry, as originally requested without applying any remappings for VFS 'use-exte...
Definition: FileEntry.h:68
DirectoryEntryRef getDir() const
Definition: FileEntry.h:78
friend bool operator==(const FileEntryRef &LHS, const FileEntryRef &RHS)
Check if the underlying FileEntry is the same, intentially ignoring whether the file was referenced w...
Definition: FileEntry.h:89
unsigned getUID() const
Definition: FileEntry.h:349
friend bool operator==(const FileEntryRef &LHS, const FileEntry *RHS)
Definition: FileEntry.h:95
Cached information about one file (either on disk or in the virtual file system).
Definition: FileEntry.h:305
const DirectoryEntry * getDir() const
Return the directory the file lives in.
Definition: FileEntry.h:338
StringRef tryGetRealPathName() const
Definition: FileEntry.h:329
friend class FileEntryTestHelper
Definition: FileEntry.h:307
void setSize(off_t NewSize)
Definition: FileEntry.h:332
time_t getModificationTime() const
Definition: FileEntry.h:335
unsigned getUID() const
Definition: FileEntry.h:333
bool isNamedPipe() const
Check whether the file is a named pipe (and thus can't be opened by the native FileManager methods).
Definition: FileEntry.h:342
void closeFile() const
Definition: FileEntry.cpp:24
off_t getSize() const
Definition: FileEntry.h:330
const llvm::sys::fs::UniqueID & getUniqueID() const
Definition: FileEntry.h:334
Implements support for file system lookup, file system caching, and directory search management.
Definition: FileManager.h:53
Customized storage for refs derived from map entires in FileManager, using the private optional_none_...
OptionalStorage(std::in_place_t, ArgTypes &&...Args)
Definition: FileEntry.h:223
OptionalStorage & operator=(clang::FileEntryRef Ref)
Definition: FileEntry.h:226
Code completion in a.
The JSON file list parser is used to communicate input to InstallAPI.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition: CallGraph.h:204
bool operator!=(CanQual< T > x, CanQual< U > y)
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
Type stored in the StringMap.
Definition: FileEntry.h:120
DirectoryEntryRef Dir
Directory the file was found in.
Definition: FileEntry.h:129
MapValue(FileEntry &FE, DirectoryEntryRef Dir)
Definition: FileEntry.h:132
MapValue(MapEntry &ME, DirectoryEntryRef Dir)
Definition: FileEntry.h:133
llvm::PointerUnion< FileEntry *, const MapEntry * > V
The pointer at another MapEntry is used when the FileManager should silently forward from one name to...
Definition: FileEntry.h:126
static unsigned getHashValue(const clang::FileEntry *Val)
Support for finding const FileEntry * in a DenseMap<FileEntryRef, T>.
Definition: FileEntry.h:272
static unsigned getHashValue(clang::FileEntryRef Val)
Definition: FileEntry.h:253
static bool isEqual(const clang::FileEntry *LHS, clang::FileEntryRef RHS)
Definition: FileEntry.h:275
static clang::FileEntryRef getTombstoneKey()
Definition: FileEntry.h:249
static clang::FileEntryRef getEmptyKey()
Definition: FileEntry.h:245
static bool isEqual(clang::FileEntryRef LHS, clang::FileEntryRef RHS)
Definition: FileEntry.h:257