clang 17.0.0git
DirectoryEntry.h
Go to the documentation of this file.
1//===- clang/Basic/DirectoryEntry.h - Directory 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::DirectoryEntry and clang::DirectoryEntryRef.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_BASIC_DIRECTORYENTRY_H
15#define LLVM_CLANG_BASIC_DIRECTORYENTRY_H
16
18#include "clang/Basic/LLVM.h"
19#include "llvm/ADT/DenseMapInfo.h"
20#include "llvm/ADT/Hashing.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/StringMap.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/Support/ErrorOr.h"
25
26#include <optional>
27#include <utility>
28
29namespace clang {
30namespace FileMgr {
31
32template <class RefTy> class MapEntryOptionalStorage;
33
34} // end namespace FileMgr
35
36/// Cached information about one directory (either on disk or in
37/// the virtual file system).
39 DirectoryEntry() = default;
40 DirectoryEntry(const DirectoryEntry &) = delete;
41 DirectoryEntry &operator=(const DirectoryEntry &) = delete;
42 friend class FileManager;
43 friend class FileEntryTestHelper;
44
45 // FIXME: We should not be storing a directory entry name here.
46 StringRef Name; // Name of the directory.
47
48public:
49 StringRef getName() const { return Name; }
50};
51
52/// A reference to a \c DirectoryEntry that includes the name of the directory
53/// as it was accessed by the FileManager's client.
55public:
56 const DirectoryEntry &getDirEntry() const { return *ME->getValue(); }
57
58 StringRef getName() const { return ME->getKey(); }
59
60 /// Hash code is based on the DirectoryEntry, not the specific named
61 /// reference.
62 friend llvm::hash_code hash_value(DirectoryEntryRef Ref) {
63 return llvm::hash_value(&Ref.getDirEntry());
64 }
65
66 using MapEntry = llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>>;
67
68 const MapEntry &getMapEntry() const { return *ME; }
69
70 /// Check if RHS referenced the file in exactly the same way.
71 bool isSameRef(DirectoryEntryRef RHS) const { return ME == RHS.ME; }
72
74 DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {}
75
76 /// Allow DirectoryEntryRef to degrade into 'const DirectoryEntry*' to
77 /// facilitate incremental adoption.
78 ///
79 /// The goal is to avoid code churn due to dances like the following:
80 /// \code
81 /// // Old code.
82 /// lvalue = rvalue;
83 ///
84 /// // Temporary code from an incremental patch.
85 /// lvalue = &rvalue.getDirectoryEntry();
86 ///
87 /// // Final code.
88 /// lvalue = rvalue;
89 /// \endcode
90 ///
91 /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::getName
92 /// has been deleted, delete this implicit conversion.
93 operator const DirectoryEntry *() const { return &getDirEntry(); }
94
95private:
97 struct optional_none_tag {};
98
99 // Private constructor for use by OptionalStorage.
100 DirectoryEntryRef(optional_none_tag) : ME(nullptr) {}
101 bool hasOptionalValue() const { return ME; }
102
103 friend struct llvm::DenseMapInfo<DirectoryEntryRef>;
104 struct dense_map_empty_tag {};
105 struct dense_map_tombstone_tag {};
106
107 // Private constructors for use by DenseMapInfo.
108 DirectoryEntryRef(dense_map_empty_tag)
109 : ME(llvm::DenseMapInfo<const MapEntry *>::getEmptyKey()) {}
110 DirectoryEntryRef(dense_map_tombstone_tag)
111 : ME(llvm::DenseMapInfo<const MapEntry *>::getTombstoneKey()) {}
112 bool isSpecialDenseMapKey() const {
113 return isSameRef(DirectoryEntryRef(dense_map_empty_tag())) ||
114 isSameRef(DirectoryEntryRef(dense_map_tombstone_tag()));
115 }
116
117 const MapEntry *ME;
118};
119
121
122namespace FileMgr {
123
124/// Customized storage for refs derived from map entires in FileManager, using
125/// the private optional_none_tag to keep it to the size of a single pointer.
126template <class RefTy> class MapEntryOptionalStorage {
127 using optional_none_tag = typename RefTy::optional_none_tag;
128 RefTy MaybeRef;
129
130public:
131 MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
132
133 template <class... ArgTypes>
134 explicit MapEntryOptionalStorage(std::in_place_t, ArgTypes &&...Args)
135 : MaybeRef(std::forward<ArgTypes>(Args)...) {}
136
137 void reset() { MaybeRef = optional_none_tag(); }
138
139 bool has_value() const { return MaybeRef.hasOptionalValue(); }
140
141 RefTy &value() & {
142 assert(has_value());
143 return MaybeRef;
144 }
145 RefTy const &value() const & {
146 assert(has_value());
147 return MaybeRef;
148 }
149 RefTy &&value() && {
150 assert(has_value());
151 return std::move(MaybeRef);
152 }
153
154 template <class... Args> void emplace(Args &&...args) {
155 MaybeRef = RefTy(std::forward<Args>(args)...);
156 }
157
159 MaybeRef = Ref;
160 return *this;
161 }
162};
163
164} // end namespace FileMgr
165
166namespace optional_detail {
167
168/// Customize OptionalStorage<DirectoryEntryRef> to use DirectoryEntryRef and
169/// its optional_none_tag to keep it the size of a single pointer.
170template <>
172 : public clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef> {
173 using StorageImpl =
175
176public:
177 OptionalStorage() = default;
178
179 template <class... ArgTypes>
180 explicit OptionalStorage(std::in_place_t, ArgTypes &&...Args)
181 : StorageImpl(std::in_place_t{}, std::forward<ArgTypes>(Args)...) {}
182
184 StorageImpl::operator=(Ref);
185 return *this;
186 }
187};
188
189static_assert(sizeof(OptionalDirectoryEntryRef) == sizeof(DirectoryEntryRef),
190 "OptionalDirectoryEntryRef must avoid size overhead");
191
192static_assert(std::is_trivially_copyable<OptionalDirectoryEntryRef>::value,
193 "OptionalDirectoryEntryRef should be trivially copyable");
194
195} // end namespace optional_detail
196} // namespace clang
197
198namespace llvm {
199/// Specialisation of DenseMapInfo for DirectoryEntryRef.
200template <> struct DenseMapInfo<clang::DirectoryEntryRef> {
203 clang::DirectoryEntryRef::dense_map_empty_tag());
204 }
205
208 clang::DirectoryEntryRef::dense_map_tombstone_tag());
209 }
210
212 return hash_value(Val);
213 }
214
217 // Catch the easy cases: both empty, both tombstone, or the same ref.
218 if (LHS.isSameRef(RHS))
219 return true;
220
221 // Confirm LHS and RHS are valid.
222 if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey())
223 return false;
224
225 // It's safe to use operator==.
226 return LHS == RHS;
227 }
228};
229
230} // end namespace llvm
231
232namespace clang {
233
234/// Wrapper around OptionalDirectoryEntryRef that degrades to 'const
235/// DirectoryEntry*', facilitating incremental patches to propagate
236/// DirectoryEntryRef.
237///
238/// This class can be used as return value or field where it's convenient for
239/// an OptionalDirectoryEntryRef to degrade to a 'const DirectoryEntry*'. The
240/// purpose is to avoid code churn due to dances like the following:
241/// \code
242/// // Old code.
243/// lvalue = rvalue;
244///
245/// // Temporary code from an incremental patch.
246/// OptionalDirectoryEntryRef MaybeF = rvalue;
247/// lvalue = MaybeF ? &MaybeF.getDirectoryEntry() : nullptr;
248///
249/// // Final code.
250/// lvalue = rvalue;
251/// \endcode
252///
253/// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::LastRef
254/// and DirectoryEntry::getName have been deleted, delete this class and
255/// replace instances with OptionalDirectoryEntryRef.
258public:
268
274 : OptionalDirectoryEntryRef(MaybeRef) {}
275
277 operator=(std::nullopt_t) {
279 return *this;
280 }
283 return *this;
284 }
288 return *this;
289 }
290
291 /// Degrade to 'const DirectoryEntry *' to allow DirectoryEntry::LastRef and
292 /// DirectoryEntry::getName have been deleted, delete this class and replace
293 /// instances with OptionalDirectoryEntryRef
294 operator const DirectoryEntry *() const {
295 return has_value() ? &(*this)->getDirEntry() : nullptr;
296 }
297};
298
299static_assert(std::is_trivially_copyable<
300 OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr>::value,
301 "OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr should be "
302 "trivially copyable");
303
304} // end namespace clang
305
306#endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
CustomizableOptional & operator=(DirectoryEntryRef &&y)
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
StringRef getName() const
DirectoryEntryRef(const MapEntry &ME)
llvm::StringMapEntry< llvm::ErrorOr< DirectoryEntry & > > MapEntry
friend llvm::hash_code hash_value(DirectoryEntryRef Ref)
Hash code is based on the DirectoryEntry, not the specific named reference.
bool isSameRef(DirectoryEntryRef RHS) const
Check if RHS referenced the file in exactly the same way.
const MapEntry & getMapEntry() const
const DirectoryEntry & getDirEntry() const
Cached information about one directory (either on disk or in the virtual file system).
StringRef getName() const
friend class FileEntryTestHelper
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_...
MapEntryOptionalStorage(std::in_place_t, ArgTypes &&...Args)
MapEntryOptionalStorage & operator=(RefTy Ref)
Wrapper around OptionalDirectoryEntryRef that degrades to 'const DirectoryEntry*',...
OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & operator=(const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &)=default
OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & operator=(std::nullopt_t)
OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(OptionalDirectoryEntryRef MaybeRef)
OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&)=default
OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & operator=(OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&)=default
OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & operator=(OptionalDirectoryEntryRef MaybeRef)
OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &)=default
OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr & operator=(DirectoryEntryRef Ref)
OptionalStorage & operator=(clang::DirectoryEntryRef Ref)
CustomizableOptional< DirectoryEntryRef > OptionalDirectoryEntryRef
YAML serialization mapping.
Definition: Dominators.h:30
Definition: Format.h:4657
static clang::DirectoryEntryRef getTombstoneKey()
static clang::DirectoryEntryRef getEmptyKey()
static unsigned getHashValue(clang::DirectoryEntryRef Val)
static bool isEqual(clang::DirectoryEntryRef LHS, clang::DirectoryEntryRef RHS)