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