File indexing completed on 2026-05-10 08:36:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_BASIC_FILEENTRY_H
0015 #define LLVM_CLANG_BASIC_FILEENTRY_H
0016
0017 #include "clang/Basic/CustomizableOptional.h"
0018 #include "clang/Basic/DirectoryEntry.h"
0019 #include "clang/Basic/LLVM.h"
0020 #include "llvm/ADT/DenseMapInfo.h"
0021 #include "llvm/ADT/Hashing.h"
0022 #include "llvm/ADT/PointerUnion.h"
0023 #include "llvm/ADT/StringMap.h"
0024 #include "llvm/ADT/StringRef.h"
0025 #include "llvm/Support/ErrorOr.h"
0026 #include "llvm/Support/FileSystem/UniqueID.h"
0027
0028 #include <optional>
0029 #include <utility>
0030
0031 namespace llvm {
0032
0033 class MemoryBuffer;
0034
0035 namespace vfs {
0036
0037 class File;
0038
0039 }
0040 }
0041
0042 namespace clang {
0043
0044 class FileEntryRef;
0045
0046 namespace optional_detail {
0047
0048
0049 template <> class OptionalStorage<clang::FileEntryRef>;
0050
0051 }
0052
0053 class FileEntry;
0054
0055
0056
0057 class FileEntryRef {
0058 public:
0059
0060
0061 StringRef getName() const { return getBaseMapEntry().first(); }
0062
0063
0064
0065
0066
0067
0068 StringRef getNameAsRequested() const { return ME->first(); }
0069
0070 const FileEntry &getFileEntry() const {
0071 return *cast<FileEntry *>(getBaseMapEntry().second->V);
0072 }
0073
0074
0075
0076 inline void updateFileEntryBufferSize(unsigned BufferSize);
0077
0078 DirectoryEntryRef getDir() const { return ME->second->Dir; }
0079
0080 inline off_t getSize() const;
0081 inline unsigned getUID() const;
0082 inline const llvm::sys::fs::UniqueID &getUniqueID() const;
0083 inline time_t getModificationTime() const;
0084 inline bool isNamedPipe() const;
0085 inline void closeFile() const;
0086
0087
0088
0089 friend bool operator==(const FileEntryRef &LHS, const FileEntryRef &RHS) {
0090 return &LHS.getFileEntry() == &RHS.getFileEntry();
0091 }
0092 friend bool operator==(const FileEntry *LHS, const FileEntryRef &RHS) {
0093 return LHS == &RHS.getFileEntry();
0094 }
0095 friend bool operator==(const FileEntryRef &LHS, const FileEntry *RHS) {
0096 return &LHS.getFileEntry() == RHS;
0097 }
0098 friend bool operator!=(const FileEntryRef &LHS, const FileEntryRef &RHS) {
0099 return !(LHS == RHS);
0100 }
0101 friend bool operator!=(const FileEntry *LHS, const FileEntryRef &RHS) {
0102 return !(LHS == RHS);
0103 }
0104 friend bool operator!=(const FileEntryRef &LHS, const FileEntry *RHS) {
0105 return !(LHS == RHS);
0106 }
0107
0108
0109
0110 friend llvm::hash_code hash_value(FileEntryRef Ref) {
0111 return llvm::hash_value(&Ref.getFileEntry());
0112 }
0113
0114 struct MapValue;
0115
0116
0117 using MapEntry = llvm::StringMapEntry<llvm::ErrorOr<MapValue>>;
0118
0119
0120 struct MapValue {
0121
0122
0123
0124
0125
0126 llvm::PointerUnion<FileEntry *, const MapEntry *> V;
0127
0128
0129 DirectoryEntryRef Dir;
0130
0131 MapValue() = delete;
0132 MapValue(FileEntry &FE, DirectoryEntryRef Dir) : V(&FE), Dir(Dir) {}
0133 MapValue(MapEntry &ME, DirectoryEntryRef Dir) : V(&ME), Dir(Dir) {}
0134 };
0135
0136
0137 bool isSameRef(const FileEntryRef &RHS) const { return ME == RHS.ME; }
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 operator const FileEntry *() const { return &getFileEntry(); }
0157
0158 FileEntryRef() = delete;
0159 explicit FileEntryRef(const MapEntry &ME) : ME(&ME) {
0160 assert(ME.second && "Expected payload");
0161 assert(ME.second->V && "Expected non-null");
0162 }
0163
0164
0165
0166 const clang::FileEntryRef::MapEntry &getMapEntry() const { return *ME; }
0167
0168
0169 const MapEntry &getBaseMapEntry() const {
0170 const MapEntry *Base = ME;
0171 while (const auto *Next = Base->second->V.dyn_cast<const MapEntry *>())
0172 Base = Next;
0173 return *Base;
0174 }
0175
0176 private:
0177 friend class FileMgr::MapEntryOptionalStorage<FileEntryRef>;
0178 struct optional_none_tag {};
0179
0180
0181 FileEntryRef(optional_none_tag) : ME(nullptr) {}
0182 bool hasOptionalValue() const { return ME; }
0183
0184 friend struct llvm::DenseMapInfo<FileEntryRef>;
0185 struct dense_map_empty_tag {};
0186 struct dense_map_tombstone_tag {};
0187
0188
0189 FileEntryRef(dense_map_empty_tag)
0190 : ME(llvm::DenseMapInfo<const MapEntry *>::getEmptyKey()) {}
0191 FileEntryRef(dense_map_tombstone_tag)
0192 : ME(llvm::DenseMapInfo<const MapEntry *>::getTombstoneKey()) {}
0193 bool isSpecialDenseMapKey() const {
0194 return isSameRef(FileEntryRef(dense_map_empty_tag())) ||
0195 isSameRef(FileEntryRef(dense_map_tombstone_tag()));
0196 }
0197
0198 const MapEntry *ME;
0199 };
0200
0201 static_assert(sizeof(FileEntryRef) == sizeof(const FileEntry *),
0202 "FileEntryRef must avoid size overhead");
0203
0204 static_assert(std::is_trivially_copyable<FileEntryRef>::value,
0205 "FileEntryRef must be trivially copyable");
0206
0207 using OptionalFileEntryRef = CustomizableOptional<FileEntryRef>;
0208
0209 namespace optional_detail {
0210
0211
0212
0213 template <>
0214 class OptionalStorage<clang::FileEntryRef>
0215 : public clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef> {
0216 using StorageImpl =
0217 clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>;
0218
0219 public:
0220 OptionalStorage() = default;
0221
0222 template <class... ArgTypes>
0223 explicit OptionalStorage(std::in_place_t, ArgTypes &&...Args)
0224 : StorageImpl(std::in_place_t{}, std::forward<ArgTypes>(Args)...) {}
0225
0226 OptionalStorage &operator=(clang::FileEntryRef Ref) {
0227 StorageImpl::operator=(Ref);
0228 return *this;
0229 }
0230 };
0231
0232 static_assert(sizeof(OptionalFileEntryRef) == sizeof(FileEntryRef),
0233 "OptionalFileEntryRef must avoid size overhead");
0234
0235 static_assert(std::is_trivially_copyable<OptionalFileEntryRef>::value,
0236 "OptionalFileEntryRef should be trivially copyable");
0237
0238 }
0239 }
0240
0241 namespace llvm {
0242
0243
0244 template <> struct DenseMapInfo<clang::FileEntryRef> {
0245 static inline clang::FileEntryRef getEmptyKey() {
0246 return clang::FileEntryRef(clang::FileEntryRef::dense_map_empty_tag());
0247 }
0248
0249 static inline clang::FileEntryRef getTombstoneKey() {
0250 return clang::FileEntryRef(clang::FileEntryRef::dense_map_tombstone_tag());
0251 }
0252
0253 static unsigned getHashValue(clang::FileEntryRef Val) {
0254 return hash_value(Val);
0255 }
0256
0257 static bool isEqual(clang::FileEntryRef LHS, clang::FileEntryRef RHS) {
0258
0259 if (LHS.isSameRef(RHS))
0260 return true;
0261
0262
0263 if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey())
0264 return false;
0265
0266
0267 return LHS == RHS;
0268 }
0269
0270
0271
0272 static unsigned getHashValue(const clang::FileEntry *Val) {
0273 return llvm::hash_value(Val);
0274 }
0275 static bool isEqual(const clang::FileEntry *LHS, clang::FileEntryRef RHS) {
0276 if (RHS.isSpecialDenseMapKey())
0277 return false;
0278 return LHS == RHS;
0279 }
0280
0281 };
0282
0283 }
0284
0285 namespace clang {
0286
0287 inline bool operator==(const FileEntry *LHS, const OptionalFileEntryRef &RHS) {
0288 return LHS == (RHS ? &RHS->getFileEntry() : nullptr);
0289 }
0290 inline bool operator==(const OptionalFileEntryRef &LHS, const FileEntry *RHS) {
0291 return (LHS ? &LHS->getFileEntry() : nullptr) == RHS;
0292 }
0293 inline bool operator!=(const FileEntry *LHS, const OptionalFileEntryRef &RHS) {
0294 return !(LHS == RHS);
0295 }
0296 inline bool operator!=(const OptionalFileEntryRef &LHS, const FileEntry *RHS) {
0297 return !(LHS == RHS);
0298 }
0299
0300
0301
0302
0303
0304
0305 class FileEntry {
0306 friend class FileManager;
0307 friend class FileEntryTestHelper;
0308 FileEntry();
0309 FileEntry(const FileEntry &) = delete;
0310 FileEntry &operator=(const FileEntry &) = delete;
0311
0312 std::string RealPathName;
0313 off_t Size = 0;
0314 time_t ModTime = 0;
0315 const DirectoryEntry *Dir = nullptr;
0316 llvm::sys::fs::UniqueID UniqueID;
0317 unsigned UID = 0;
0318 bool IsNamedPipe = false;
0319
0320
0321 mutable std::unique_ptr<llvm::vfs::File> File;
0322
0323
0324 std::unique_ptr<llvm::MemoryBuffer> Content;
0325
0326 public:
0327 ~FileEntry();
0328
0329 StringRef tryGetRealPathName() const { return RealPathName; }
0330 off_t getSize() const { return Size; }
0331
0332 void setSize(off_t NewSize) { Size = NewSize; }
0333 unsigned getUID() const { return UID; }
0334 const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
0335 time_t getModificationTime() const { return ModTime; }
0336
0337
0338 const DirectoryEntry *getDir() const { return Dir; }
0339
0340
0341
0342 bool isNamedPipe() const { return IsNamedPipe; }
0343
0344 void closeFile() const;
0345 };
0346
0347 off_t FileEntryRef::getSize() const { return getFileEntry().getSize(); }
0348
0349 unsigned FileEntryRef::getUID() const { return getFileEntry().getUID(); }
0350
0351 const llvm::sys::fs::UniqueID &FileEntryRef::getUniqueID() const {
0352 return getFileEntry().getUniqueID();
0353 }
0354
0355 time_t FileEntryRef::getModificationTime() const {
0356 return getFileEntry().getModificationTime();
0357 }
0358
0359 bool FileEntryRef::isNamedPipe() const { return getFileEntry().isNamedPipe(); }
0360
0361 void FileEntryRef::closeFile() const { getFileEntry().closeFile(); }
0362
0363 void FileEntryRef::updateFileEntryBufferSize(unsigned BufferSize) {
0364 cast<FileEntry *>(getBaseMapEntry().second->V)->setSize(BufferSize);
0365 }
0366
0367 }
0368
0369 #endif