clang 18.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 LLVM_DEPRECATED("Use DirectoryEntryRef::getName() instead.", "")
50 StringRef getName() const { return Name; }
51};
52
53/// A reference to a \c DirectoryEntry that includes the name of the directory
54/// as it was accessed by the FileManager's client.
56public:
57 const DirectoryEntry &getDirEntry() const { return *ME->getValue(); }
58
59 StringRef getName() const { return ME->getKey(); }
60
61 /// Hash code is based on the DirectoryEntry, not the specific named
62 /// reference.
63 friend llvm::hash_code hash_value(DirectoryEntryRef Ref) {
64 return llvm::hash_value(&Ref.getDirEntry());
65 }
66
67 using MapEntry = llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>>;
68
69 const MapEntry &getMapEntry() const { return *ME; }
70
71 /// Check if RHS referenced the file in exactly the same way.
72 bool isSameRef(DirectoryEntryRef RHS) const { return ME == RHS.ME; }
73
75 explicit DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {}
76
77 /// Allow DirectoryEntryRef to degrade into 'const DirectoryEntry*' to
78 /// facilitate incremental adoption.
79 ///
80 /// The goal is to avoid code churn due to dances like the following:
81 /// \code
82 /// // Old code.
83 /// lvalue = rvalue;
84 ///
85 /// // Temporary code from an incremental patch.
86 /// lvalue = &rvalue.getDirectoryEntry();
87 ///
88 /// // Final code.
89 /// lvalue = rvalue;
90 /// \endcode
91 ///
92 /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::getName
93 /// has been deleted, delete this implicit conversion.
94 operator const DirectoryEntry *() const { return &getDirEntry(); }
95
96private:
98 struct optional_none_tag {};
99
100 // Private constructor for use by OptionalStorage.
101 DirectoryEntryRef(optional_none_tag) : ME(nullptr) {}
102 bool hasOptionalValue() const { return ME; }
103
104 friend struct llvm::DenseMapInfo<DirectoryEntryRef>;
105 struct dense_map_empty_tag {};
106 struct dense_map_tombstone_tag {};
107
108 // Private constructors for use by DenseMapInfo.
109 DirectoryEntryRef(dense_map_empty_tag)
110 : ME(llvm::DenseMapInfo<const MapEntry *>::getEmptyKey()) {}
111 DirectoryEntryRef(dense_map_tombstone_tag)
112 : ME(llvm::DenseMapInfo<const MapEntry *>::getTombstoneKey()) {}
113 bool isSpecialDenseMapKey() const {
114 return isSameRef(DirectoryEntryRef(dense_map_empty_tag())) ||
115 isSameRef(DirectoryEntryRef(dense_map_tombstone_tag()));
116 }
117
118 const MapEntry *ME;
119};
120
122
123namespace FileMgr {
124
125/// Customized storage for refs derived from map entires in FileManager, using
126/// the private optional_none_tag to keep it to the size of a single pointer.
127template <class RefTy> class MapEntryOptionalStorage {
128 using optional_none_tag = typename RefTy::optional_none_tag;
129 RefTy MaybeRef;
130
131public:
132 MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
133
134 template <class... ArgTypes>
135 explicit MapEntryOptionalStorage(std::in_place_t, ArgTypes &&...Args)
136 : MaybeRef(std::forward<ArgTypes>(Args)...) {}
137
138 void reset() { MaybeRef = optional_none_tag(); }
139
140 bool has_value() const { return MaybeRef.hasOptionalValue(); }
141
142 RefTy &value() & {
143 assert(has_value());
144 return MaybeRef;
145 }
146 RefTy const &value() const & {
147 assert(has_value());
148 return MaybeRef;
149 }
150 RefTy &&value() && {
151 assert(has_value());
152 return std::move(MaybeRef);
153 }
154
155 template <class... Args> void emplace(Args &&...args) {
156 MaybeRef = RefTy(std::forward<Args>(args)...);
157 }
158
160 MaybeRef = Ref;
161 return *this;
162 }
163};
164
165} // end namespace FileMgr
166
167namespace optional_detail {
168
169/// Customize OptionalStorage<DirectoryEntryRef> to use DirectoryEntryRef and
170/// its optional_none_tag to keep it the size of a single pointer.
171template <>
173 : public clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef> {
174 using StorageImpl =
176
177public:
178 OptionalStorage() = default;
179
180 template <class... ArgTypes>
181 explicit OptionalStorage(std::in_place_t, ArgTypes &&...Args)
182 : StorageImpl(std::in_place_t{}, std::forward<ArgTypes>(Args)...) {}
183
185 StorageImpl::operator=(Ref);
186 return *this;
187 }
188};
189
190static_assert(sizeof(OptionalDirectoryEntryRef) == sizeof(DirectoryEntryRef),
191 "OptionalDirectoryEntryRef must avoid size overhead");
192
193static_assert(std::is_trivially_copyable<OptionalDirectoryEntryRef>::value,
194 "OptionalDirectoryEntryRef should be trivially copyable");
195
196} // end namespace optional_detail
197} // namespace clang
198
199namespace llvm {
200
201template <> struct PointerLikeTypeTraits<clang::DirectoryEntryRef> {
203 return const_cast<clang::DirectoryEntryRef::MapEntry *>(&Dir.getMapEntry());
204 }
205
208 *reinterpret_cast<const clang::DirectoryEntryRef::MapEntry *>(Ptr));
209 }
210
211 static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<
212 const clang::DirectoryEntryRef::MapEntry *>::NumLowBitsAvailable;
213};
214
215/// Specialisation of DenseMapInfo for DirectoryEntryRef.
216template <> struct DenseMapInfo<clang::DirectoryEntryRef> {
219 clang::DirectoryEntryRef::dense_map_empty_tag());
220 }
221
224 clang::DirectoryEntryRef::dense_map_tombstone_tag());
225 }
226
228 return hash_value(Val);
229 }
230
233 // Catch the easy cases: both empty, both tombstone, or the same ref.
234 if (LHS.isSameRef(RHS))
235 return true;
236
237 // Confirm LHS and RHS are valid.
238 if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey())
239 return false;
240
241 // It's safe to use operator==.
242 return LHS == RHS;
243 }
244};
245
246} // end namespace llvm
247
248namespace clang {
249
250/// Wrapper around OptionalDirectoryEntryRef that degrades to 'const
251/// DirectoryEntry*', facilitating incremental patches to propagate
252/// DirectoryEntryRef.
253///
254/// This class can be used as return value or field where it's convenient for
255/// an OptionalDirectoryEntryRef to degrade to a 'const DirectoryEntry*'. The
256/// purpose is to avoid code churn due to dances like the following:
257/// \code
258/// // Old code.
259/// lvalue = rvalue;
260///
261/// // Temporary code from an incremental patch.
262/// OptionalDirectoryEntryRef MaybeF = rvalue;
263/// lvalue = MaybeF ? &MaybeF.getDirectoryEntry() : nullptr;
264///
265/// // Final code.
266/// lvalue = rvalue;
267/// \endcode
268///
269/// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::LastRef
270/// and DirectoryEntry::getName have been deleted, delete this class and
271/// replace instances with OptionalDirectoryEntryRef.
274public:
284
290 : OptionalDirectoryEntryRef(MaybeRef) {}
291
293 operator=(std::nullopt_t) {
295 return *this;
296 }
299 return *this;
300 }
304 return *this;
305 }
306
307 /// Degrade to 'const DirectoryEntry *' to allow DirectoryEntry::LastRef and
308 /// DirectoryEntry::getName have been deleted, delete this class and replace
309 /// instances with OptionalDirectoryEntryRef
310 operator const DirectoryEntry *() const {
311 return has_value() ? &(*this)->getDirEntry() : nullptr;
312 }
313};
314
315static_assert(std::is_trivially_copyable<
316 OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr>::value,
317 "OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr should be "
318 "trivially copyable");
319
320} // end namespace clang
321
322#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)
Code completion in a.
CustomizableOptional< DirectoryEntryRef > OptionalDirectoryEntryRef
YAML serialization mapping.
Definition: Dominators.h:30
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
Definition: Format.h:5078
static clang::DirectoryEntryRef getTombstoneKey()
static clang::DirectoryEntryRef getEmptyKey()
static unsigned getHashValue(clang::DirectoryEntryRef Val)
static bool isEqual(clang::DirectoryEntryRef LHS, clang::DirectoryEntryRef RHS)
static clang::DirectoryEntryRef getFromVoidPointer(void *Ptr)
static void * getAsVoidPointer(clang::DirectoryEntryRef Dir)