@@ -31,16 +31,32 @@ class File;
31
31
32
32
namespace clang {
33
33
34
+ class FileEntryRef ;
35
+
36
+ } // namespace clang
37
+
38
+ namespace llvm {
39
+ namespace optional_detail {
40
+
41
+ // / Forward declare a template specialization for OptionalStorage.
42
+ template <>
43
+ class OptionalStorage <clang::FileEntryRef, /* is_trivially_copyable*/ true >;
44
+
45
+ } // namespace optional_detail
46
+ } // namespace llvm
47
+
48
+ namespace clang {
49
+
34
50
class DirectoryEntry ;
35
51
class FileEntry ;
36
52
37
53
// / A reference to a \c FileEntry that includes the name of the file as it was
38
54
// / accessed by the FileManager's client.
39
55
class FileEntryRef {
40
56
public:
41
- const StringRef getName () const { return Entry ->first (); }
57
+ StringRef getName () const { return ME ->first (); }
42
58
const FileEntry &getFileEntry () const {
43
- return *Entry ->second ->V .get <FileEntry *>();
59
+ return *ME ->second ->V .get <FileEntry *>();
44
60
}
45
61
46
62
inline bool isValid () const ;
@@ -49,12 +65,26 @@ class FileEntryRef {
49
65
inline const llvm::sys::fs::UniqueID &getUniqueID () const ;
50
66
inline time_t getModificationTime () const ;
51
67
68
+ // / Check if the underlying FileEntry is the same, intentially ignoring
69
+ // / whether the file was referenced with the same spelling of the filename.
52
70
friend bool operator ==(const FileEntryRef &LHS, const FileEntryRef &RHS) {
53
- return LHS.Entry == RHS.Entry ;
71
+ return &LHS.getFileEntry () == &RHS.getFileEntry ();
72
+ }
73
+ friend bool operator ==(const FileEntry *LHS, const FileEntryRef &RHS) {
74
+ return LHS == &RHS.getFileEntry ();
75
+ }
76
+ friend bool operator ==(const FileEntryRef &LHS, const FileEntry *RHS) {
77
+ return &LHS.getFileEntry () == RHS;
54
78
}
55
79
friend bool operator !=(const FileEntryRef &LHS, const FileEntryRef &RHS) {
56
80
return !(LHS == RHS);
57
81
}
82
+ friend bool operator !=(const FileEntry *LHS, const FileEntryRef &RHS) {
83
+ return !(LHS == RHS);
84
+ }
85
+ friend bool operator !=(const FileEntryRef &LHS, const FileEntry *RHS) {
86
+ return !(LHS == RHS);
87
+ }
58
88
59
89
struct MapValue ;
60
90
@@ -78,20 +108,190 @@ class FileEntryRef {
78
108
MapValue (MapEntry &ME) : V(&ME) {}
79
109
};
80
110
81
- private:
82
- friend class FileManager ;
111
+ // / Check if RHS referenced the file in exactly the same way.
112
+ bool isSameRef (const FileEntryRef &RHS) const { return ME == RHS.ME ; }
113
+
114
+ // / Allow FileEntryRef to degrade into 'const FileEntry*' to facilitate
115
+ // / incremental adoption.
116
+ // /
117
+ // / The goal is to avoid code churn due to dances like the following:
118
+ // / \code
119
+ // / // Old code.
120
+ // / lvalue = rvalue;
121
+ // /
122
+ // / // Temporary code from an incremental patch.
123
+ // / lvalue = &rvalue.getFileEntry();
124
+ // /
125
+ // / // Final code.
126
+ // / lvalue = rvalue;
127
+ // / \endcode
128
+ // /
129
+ // / FIXME: Once FileEntryRef is "everywhere" and FileEntry::LastRef and
130
+ // / FileEntry::getName have been deleted, delete this implicit conversion.
131
+ operator const FileEntry *() const { return &getFileEntry (); }
83
132
84
133
FileEntryRef () = delete ;
85
- explicit FileEntryRef (const MapEntry &Entry)
86
- : Entry(&Entry) {
87
- assert (Entry.second && " Expected payload" );
88
- assert (Entry.second ->V && " Expected non-null" );
89
- assert (Entry.second ->V .is <FileEntry *>() && " Expected FileEntry" );
134
+ explicit FileEntryRef (const MapEntry &ME) : ME(&ME) {
135
+ assert (ME.second && " Expected payload" );
136
+ assert (ME.second ->V && " Expected non-null" );
137
+ assert (ME.second ->V .is <FileEntry *>() && " Expected FileEntry" );
138
+ }
139
+
140
+ // / Expose the underlying MapEntry to simplify packing in a PointerIntPair or
141
+ // / PointerUnion and allow construction in Optional.
142
+ const clang::FileEntryRef::MapEntry &getMapEntry () const { return *ME; }
143
+
144
+ private:
145
+ friend class llvm ::optional_detail::OptionalStorage<
146
+ FileEntryRef, /* is_trivially_copyable*/ true >;
147
+ struct optional_none_tag {};
148
+
149
+ // Private constructor for use by OptionalStorage.
150
+ FileEntryRef (optional_none_tag) : ME(nullptr ) {}
151
+ bool hasOptionalValue () const { return ME; }
152
+
153
+ const MapEntry *ME;
154
+ };
155
+
156
+ static_assert (sizeof (FileEntryRef) == sizeof (const FileEntry *),
157
+ " FileEntryRef must avoid size overhead" );
158
+
159
+ static_assert (std::is_trivially_copyable<FileEntryRef>::value,
160
+ " FileEntryRef must be trivially copyable" );
161
+
162
+ } // end namespace clang
163
+
164
+ namespace llvm {
165
+ namespace optional_detail {
166
+
167
+ // / Customize OptionalStorage<FileEntryRef> to use FileEntryRef and its
168
+ // / optional_none_tag to keep it the size of a single pointer.
169
+ template <> class OptionalStorage <clang::FileEntryRef> {
170
+ clang::FileEntryRef MaybeRef = clang::FileEntryRef::optional_none_tag{};
171
+
172
+ public:
173
+ ~OptionalStorage () = default ;
174
+ constexpr OptionalStorage () noexcept = default;
175
+ constexpr OptionalStorage (OptionalStorage const &Other) = default;
176
+ constexpr OptionalStorage (OptionalStorage &&Other) = default;
177
+ OptionalStorage &operator =(OptionalStorage const &Other) = default ;
178
+ OptionalStorage &operator =(OptionalStorage &&Other) = default ;
179
+
180
+ template <class ... ArgTypes>
181
+ constexpr explicit OptionalStorage (in_place_t , ArgTypes &&...Args)
182
+ : MaybeRef(std::forward<ArgTypes>(Args)...) {}
183
+
184
+ void reset () noexcept { MaybeRef = clang::FileEntryRef::optional_none_tag (); }
185
+
186
+ constexpr bool hasValue () const noexcept {
187
+ return MaybeRef.hasOptionalValue ();
188
+ }
189
+
190
+ clang::FileEntryRef &getValue () LLVM_LVALUE_FUNCTION noexcept {
191
+ assert (hasValue ());
192
+ return MaybeRef;
193
+ }
194
+ constexpr clang::FileEntryRef const &
195
+ getValue () const LLVM_LVALUE_FUNCTION noexcept {
196
+ assert (hasValue ());
197
+ return MaybeRef;
198
+ }
199
+ #if LLVM_HAS_RVALUE_REFERENCE_THIS
200
+ clang::FileEntryRef &&getValue() &&noexcept {
201
+ assert (hasValue ());
202
+ return std::move (MaybeRef);
203
+ }
204
+ #endif
205
+
206
+ template <class ... Args> void emplace (Args &&...args) {
207
+ MaybeRef = clang::FileEntryRef (std::forward<Args>(args)...);
90
208
}
91
209
92
- const MapEntry *Entry;
210
+ OptionalStorage &operator =(clang::FileEntryRef Ref) {
211
+ MaybeRef = Ref;
212
+ return *this ;
213
+ }
93
214
};
94
215
216
+ static_assert (sizeof (Optional<clang::FileEntryRef>) ==
217
+ sizeof (clang::FileEntryRef),
218
+ " Optional<FileEntryRef> must avoid size overhead" );
219
+
220
+ static_assert (std::is_trivially_copyable<Optional<clang::FileEntryRef>>::value,
221
+ " Optional<FileEntryRef> should be trivially copyable" );
222
+
223
+ } // end namespace optional_detail
224
+ } // end namespace llvm
225
+
226
+ namespace clang {
227
+
228
+ // / Wrapper around Optional<FileEntryRef> that degrades to 'const FileEntry*',
229
+ // / facilitating incremental patches to propagate FileEntryRef.
230
+ // /
231
+ // / This class can be used as return value or field where it's convenient for
232
+ // / an Optional<FileEntryRef> to degrade to a 'const FileEntry*'. The purpose
233
+ // / is to avoid code churn due to dances like the following:
234
+ // / \code
235
+ // / // Old code.
236
+ // / lvalue = rvalue;
237
+ // /
238
+ // / // Temporary code from an incremental patch.
239
+ // / Optional<FileEntryRef> MaybeF = rvalue;
240
+ // / lvalue = MaybeF ? &MaybeF.getFileEntry() : nullptr;
241
+ // /
242
+ // / // Final code.
243
+ // / lvalue = rvalue;
244
+ // / \endcode
245
+ // /
246
+ // / FIXME: Once FileEntryRef is "everywhere" and FileEntry::LastRef and
247
+ // / FileEntry::getName have been deleted, delete this class and replace
248
+ // / instances with Optional<FileEntryRef>.
249
+ class OptionalFileEntryRefDegradesToFileEntryPtr
250
+ : public Optional<FileEntryRef> {
251
+ public:
252
+ constexpr OptionalFileEntryRefDegradesToFileEntryPtr () noexcept = default;
253
+ constexpr OptionalFileEntryRefDegradesToFileEntryPtr (
254
+ OptionalFileEntryRefDegradesToFileEntryPtr &&) = default;
255
+ constexpr OptionalFileEntryRefDegradesToFileEntryPtr (
256
+ const OptionalFileEntryRefDegradesToFileEntryPtr &) = default;
257
+ OptionalFileEntryRefDegradesToFileEntryPtr &
258
+ operator =(OptionalFileEntryRefDegradesToFileEntryPtr &&) = default ;
259
+ OptionalFileEntryRefDegradesToFileEntryPtr &
260
+ operator =(const OptionalFileEntryRefDegradesToFileEntryPtr &) = default ;
261
+
262
+ OptionalFileEntryRefDegradesToFileEntryPtr (llvm::NoneType) {}
263
+ OptionalFileEntryRefDegradesToFileEntryPtr (FileEntryRef Ref)
264
+ : Optional<FileEntryRef>(Ref) {}
265
+ OptionalFileEntryRefDegradesToFileEntryPtr (Optional<FileEntryRef> MaybeRef)
266
+ : Optional<FileEntryRef>(MaybeRef) {}
267
+
268
+ OptionalFileEntryRefDegradesToFileEntryPtr &operator =(llvm::NoneType) {
269
+ Optional<FileEntryRef>::operator =(None);
270
+ return *this ;
271
+ }
272
+ OptionalFileEntryRefDegradesToFileEntryPtr &operator =(FileEntryRef Ref) {
273
+ Optional<FileEntryRef>::operator =(Ref);
274
+ return *this ;
275
+ }
276
+ OptionalFileEntryRefDegradesToFileEntryPtr &
277
+ operator =(Optional<FileEntryRef> MaybeRef) {
278
+ Optional<FileEntryRef>::operator =(MaybeRef);
279
+ return *this ;
280
+ }
281
+
282
+ // / Degrade to 'const FileEntry *' to allow FileEntry::LastRef and
283
+ // / FileEntry::getName have been deleted, delete this class and replace
284
+ // / instances with Optional<FileEntryRef>
285
+ operator const FileEntry *() const {
286
+ return hasValue () ? &getValue ().getFileEntry () : nullptr ;
287
+ }
288
+ };
289
+
290
+ static_assert (
291
+ std::is_trivially_copyable<
292
+ OptionalFileEntryRefDegradesToFileEntryPtr>::value,
293
+ " OptionalFileEntryRefDegradesToFileEntryPtr should be trivially copyable" );
294
+
95
295
// / Cached information about one file (either on disk
96
296
// / or in the virtual file system).
97
297
// /
@@ -147,10 +347,6 @@ class FileEntry {
147
347
bool isNamedPipe () const { return IsNamedPipe; }
148
348
149
349
void closeFile () const ;
150
-
151
- // Only for use in tests to see if deferred opens are happening, rather than
152
- // relying on RealPathName being empty.
153
- bool isOpenForTests () const { return File != nullptr ; }
154
350
};
155
351
156
352
bool FileEntryRef::isValid () const { return getFileEntry ().isValid (); }
0 commit comments