DirectoryEntry.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- clang/Basic/DirectoryEntry.h - Directory references ------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// Defines interfaces for clang::DirectoryEntry and clang::DirectoryEntryRef.
  16. ///
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_BASIC_DIRECTORYENTRY_H
  19. #define LLVM_CLANG_BASIC_DIRECTORYENTRY_H
  20. #include "clang/Basic/LLVM.h"
  21. #include "llvm/ADT/DenseMapInfo.h"
  22. #include "llvm/ADT/Hashing.h"
  23. #include "llvm/ADT/StringMap.h"
  24. #include "llvm/ADT/StringRef.h"
  25. #include "llvm/ADT/STLExtras.h"
  26. #include "llvm/Support/ErrorOr.h"
  27. namespace clang {
  28. namespace FileMgr {
  29. template <class RefTy> class MapEntryOptionalStorage;
  30. } // end namespace FileMgr
  31. /// Cached information about one directory (either on disk or in
  32. /// the virtual file system).
  33. class DirectoryEntry {
  34. friend class FileManager;
  35. // FIXME: We should not be storing a directory entry name here.
  36. StringRef Name; // Name of the directory.
  37. public:
  38. StringRef getName() const { return Name; }
  39. };
  40. /// A reference to a \c DirectoryEntry that includes the name of the directory
  41. /// as it was accessed by the FileManager's client.
  42. class DirectoryEntryRef {
  43. public:
  44. const DirectoryEntry &getDirEntry() const { return *ME->getValue(); }
  45. StringRef getName() const { return ME->getKey(); }
  46. /// Hash code is based on the DirectoryEntry, not the specific named
  47. /// reference.
  48. friend llvm::hash_code hash_value(DirectoryEntryRef Ref) {
  49. return llvm::hash_value(&Ref.getDirEntry());
  50. }
  51. using MapEntry = llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>>;
  52. const MapEntry &getMapEntry() const { return *ME; }
  53. /// Check if RHS referenced the file in exactly the same way.
  54. bool isSameRef(DirectoryEntryRef RHS) const { return ME == RHS.ME; }
  55. DirectoryEntryRef() = delete;
  56. DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {}
  57. /// Allow DirectoryEntryRef to degrade into 'const DirectoryEntry*' to
  58. /// facilitate incremental adoption.
  59. ///
  60. /// The goal is to avoid code churn due to dances like the following:
  61. /// \code
  62. /// // Old code.
  63. /// lvalue = rvalue;
  64. ///
  65. /// // Temporary code from an incremental patch.
  66. /// lvalue = &rvalue.getDirectoryEntry();
  67. ///
  68. /// // Final code.
  69. /// lvalue = rvalue;
  70. /// \endcode
  71. ///
  72. /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::getName
  73. /// has been deleted, delete this implicit conversion.
  74. operator const DirectoryEntry *() const { return &getDirEntry(); }
  75. private:
  76. friend class FileMgr::MapEntryOptionalStorage<DirectoryEntryRef>;
  77. struct optional_none_tag {};
  78. // Private constructor for use by OptionalStorage.
  79. DirectoryEntryRef(optional_none_tag) : ME(nullptr) {}
  80. bool hasOptionalValue() const { return ME; }
  81. friend struct llvm::DenseMapInfo<DirectoryEntryRef>;
  82. struct dense_map_empty_tag {};
  83. struct dense_map_tombstone_tag {};
  84. // Private constructors for use by DenseMapInfo.
  85. DirectoryEntryRef(dense_map_empty_tag)
  86. : ME(llvm::DenseMapInfo<const MapEntry *>::getEmptyKey()) {}
  87. DirectoryEntryRef(dense_map_tombstone_tag)
  88. : ME(llvm::DenseMapInfo<const MapEntry *>::getTombstoneKey()) {}
  89. bool isSpecialDenseMapKey() const {
  90. return isSameRef(DirectoryEntryRef(dense_map_empty_tag())) ||
  91. isSameRef(DirectoryEntryRef(dense_map_tombstone_tag()));
  92. }
  93. const MapEntry *ME;
  94. };
  95. namespace FileMgr {
  96. /// Customized storage for refs derived from map entires in FileManager, using
  97. /// the private optional_none_tag to keep it to the size of a single pointer.
  98. template <class RefTy> class MapEntryOptionalStorage {
  99. using optional_none_tag = typename RefTy::optional_none_tag;
  100. RefTy MaybeRef;
  101. public:
  102. MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
  103. template <class... ArgTypes>
  104. explicit MapEntryOptionalStorage(llvm::in_place_t, ArgTypes &&...Args)
  105. : MaybeRef(std::forward<ArgTypes>(Args)...) {}
  106. void reset() { MaybeRef = optional_none_tag(); }
  107. bool hasValue() const { return MaybeRef.hasOptionalValue(); }
  108. RefTy &getValue() LLVM_LVALUE_FUNCTION {
  109. assert(hasValue());
  110. return MaybeRef;
  111. }
  112. RefTy const &getValue() const LLVM_LVALUE_FUNCTION {
  113. assert(hasValue());
  114. return MaybeRef;
  115. }
  116. #if LLVM_HAS_RVALUE_REFERENCE_THIS
  117. RefTy &&getValue() && {
  118. assert(hasValue());
  119. return std::move(MaybeRef);
  120. }
  121. #endif
  122. template <class... Args> void emplace(Args &&...args) {
  123. MaybeRef = RefTy(std::forward<Args>(args)...);
  124. }
  125. MapEntryOptionalStorage &operator=(RefTy Ref) {
  126. MaybeRef = Ref;
  127. return *this;
  128. }
  129. };
  130. } // end namespace FileMgr
  131. } // end namespace clang
  132. namespace llvm {
  133. namespace optional_detail {
  134. /// Customize OptionalStorage<DirectoryEntryRef> to use DirectoryEntryRef and
  135. /// its optional_none_tag to keep it the size of a single pointer.
  136. template <>
  137. class OptionalStorage<clang::DirectoryEntryRef>
  138. : public clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef> {
  139. using StorageImpl =
  140. clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>;
  141. public:
  142. OptionalStorage() = default;
  143. template <class... ArgTypes>
  144. explicit OptionalStorage(in_place_t, ArgTypes &&...Args)
  145. : StorageImpl(in_place_t{}, std::forward<ArgTypes>(Args)...) {}
  146. OptionalStorage &operator=(clang::DirectoryEntryRef Ref) {
  147. StorageImpl::operator=(Ref);
  148. return *this;
  149. }
  150. };
  151. static_assert(sizeof(Optional<clang::DirectoryEntryRef>) ==
  152. sizeof(clang::DirectoryEntryRef),
  153. "Optional<DirectoryEntryRef> must avoid size overhead");
  154. static_assert(
  155. std::is_trivially_copyable<Optional<clang::DirectoryEntryRef>>::value,
  156. "Optional<DirectoryEntryRef> should be trivially copyable");
  157. } // end namespace optional_detail
  158. /// Specialisation of DenseMapInfo for DirectoryEntryRef.
  159. template <> struct DenseMapInfo<clang::DirectoryEntryRef> {
  160. static inline clang::DirectoryEntryRef getEmptyKey() {
  161. return clang::DirectoryEntryRef(
  162. clang::DirectoryEntryRef::dense_map_empty_tag());
  163. }
  164. static inline clang::DirectoryEntryRef getTombstoneKey() {
  165. return clang::DirectoryEntryRef(
  166. clang::DirectoryEntryRef::dense_map_tombstone_tag());
  167. }
  168. static unsigned getHashValue(clang::DirectoryEntryRef Val) {
  169. return hash_value(Val);
  170. }
  171. static bool isEqual(clang::DirectoryEntryRef LHS,
  172. clang::DirectoryEntryRef RHS) {
  173. // Catch the easy cases: both empty, both tombstone, or the same ref.
  174. if (LHS.isSameRef(RHS))
  175. return true;
  176. // Confirm LHS and RHS are valid.
  177. if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey())
  178. return false;
  179. // It's safe to use operator==.
  180. return LHS == RHS;
  181. }
  182. };
  183. } // end namespace llvm
  184. namespace clang {
  185. /// Wrapper around Optional<DirectoryEntryRef> that degrades to 'const
  186. /// DirectoryEntry*', facilitating incremental patches to propagate
  187. /// DirectoryEntryRef.
  188. ///
  189. /// This class can be used as return value or field where it's convenient for
  190. /// an Optional<DirectoryEntryRef> to degrade to a 'const DirectoryEntry*'. The
  191. /// purpose is to avoid code churn due to dances like the following:
  192. /// \code
  193. /// // Old code.
  194. /// lvalue = rvalue;
  195. ///
  196. /// // Temporary code from an incremental patch.
  197. /// Optional<DirectoryEntryRef> MaybeF = rvalue;
  198. /// lvalue = MaybeF ? &MaybeF.getDirectoryEntry() : nullptr;
  199. ///
  200. /// // Final code.
  201. /// lvalue = rvalue;
  202. /// \endcode
  203. ///
  204. /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::LastRef
  205. /// and DirectoryEntry::getName have been deleted, delete this class and
  206. /// replace instances with Optional<DirectoryEntryRef>.
  207. class OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr
  208. : public Optional<DirectoryEntryRef> {
  209. public:
  210. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr() = default;
  211. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
  212. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
  213. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
  214. const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
  215. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
  216. operator=(OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
  217. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
  218. operator=(const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
  219. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(llvm::NoneType) {}
  220. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(DirectoryEntryRef Ref)
  221. : Optional<DirectoryEntryRef>(Ref) {}
  222. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(Optional<DirectoryEntryRef> MaybeRef)
  223. : Optional<DirectoryEntryRef>(MaybeRef) {}
  224. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(llvm::NoneType) {
  225. Optional<DirectoryEntryRef>::operator=(None);
  226. return *this;
  227. }
  228. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(DirectoryEntryRef Ref) {
  229. Optional<DirectoryEntryRef>::operator=(Ref);
  230. return *this;
  231. }
  232. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
  233. operator=(Optional<DirectoryEntryRef> MaybeRef) {
  234. Optional<DirectoryEntryRef>::operator=(MaybeRef);
  235. return *this;
  236. }
  237. /// Degrade to 'const DirectoryEntry *' to allow DirectoryEntry::LastRef and
  238. /// DirectoryEntry::getName have been deleted, delete this class and replace
  239. /// instances with Optional<DirectoryEntryRef>
  240. operator const DirectoryEntry *() const {
  241. return hasValue() ? &getValue().getDirEntry() : nullptr;
  242. }
  243. };
  244. static_assert(std::is_trivially_copyable<
  245. OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr>::value,
  246. "OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr should be "
  247. "trivially copyable");
  248. } // end namespace clang
  249. #endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H
  250. #ifdef __GNUC__
  251. #pragma GCC diagnostic pop
  252. #endif