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