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