clang  20.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 
29 namespace clang {
30 namespace FileMgr {
31 
32 template <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 
46 /// A reference to a \c DirectoryEntry that includes the name of the directory
47 /// as it was accessed by the FileManager's client.
49 public:
50  const DirectoryEntry &getDirEntry() const { return *ME->getValue(); }
51 
52  StringRef getName() const { return ME->getKey(); }
53 
54  /// Hash code is based on the DirectoryEntry, not the specific named
55  /// reference.
56  friend llvm::hash_code hash_value(DirectoryEntryRef Ref) {
57  return llvm::hash_value(&Ref.getDirEntry());
58  }
59 
60  using MapEntry = llvm::StringMapEntry<llvm::ErrorOr<DirectoryEntry &>>;
61 
62  const MapEntry &getMapEntry() const { return *ME; }
63 
64  /// Check if RHS referenced the file in exactly the same way.
65  bool isSameRef(DirectoryEntryRef RHS) const { return ME == RHS.ME; }
66 
67  DirectoryEntryRef() = delete;
68  explicit DirectoryEntryRef(const MapEntry &ME) : ME(&ME) {}
69 
70  /// Allow DirectoryEntryRef to degrade into 'const DirectoryEntry*' to
71  /// facilitate incremental adoption.
72  ///
73  /// The goal is to avoid code churn due to dances like the following:
74  /// \code
75  /// // Old code.
76  /// lvalue = rvalue;
77  ///
78  /// // Temporary code from an incremental patch.
79  /// lvalue = &rvalue.getDirectoryEntry();
80  ///
81  /// // Final code.
82  /// lvalue = rvalue;
83  /// \endcode
84  ///
85  /// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::getName
86  /// has been deleted, delete this implicit conversion.
87  operator const DirectoryEntry *() const { return &getDirEntry(); }
88 
89 private:
91  struct optional_none_tag {};
92 
93  // Private constructor for use by OptionalStorage.
94  DirectoryEntryRef(optional_none_tag) : ME(nullptr) {}
95  bool hasOptionalValue() const { return ME; }
96 
97  friend struct llvm::DenseMapInfo<DirectoryEntryRef>;
98  struct dense_map_empty_tag {};
99  struct dense_map_tombstone_tag {};
100 
101  // Private constructors for use by DenseMapInfo.
102  DirectoryEntryRef(dense_map_empty_tag)
103  : ME(llvm::DenseMapInfo<const MapEntry *>::getEmptyKey()) {}
104  DirectoryEntryRef(dense_map_tombstone_tag)
105  : ME(llvm::DenseMapInfo<const MapEntry *>::getTombstoneKey()) {}
106  bool isSpecialDenseMapKey() const {
107  return isSameRef(DirectoryEntryRef(dense_map_empty_tag())) ||
108  isSameRef(DirectoryEntryRef(dense_map_tombstone_tag()));
109  }
110 
111  const MapEntry *ME;
112 };
113 
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(std::in_place_t, ArgTypes &&...Args)
129  : MaybeRef(std::forward<ArgTypes>(Args)...) {}
130 
131  void reset() { MaybeRef = optional_none_tag(); }
132 
133  bool has_value() const { return MaybeRef.hasOptionalValue(); }
134 
135  RefTy &value() & {
136  assert(has_value());
137  return MaybeRef;
138  }
139  RefTy const &value() const & {
140  assert(has_value());
141  return MaybeRef;
142  }
143  RefTy &&value() && {
144  assert(has_value());
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 
160 namespace optional_detail {
161 
162 /// Customize OptionalStorage<DirectoryEntryRef> to use DirectoryEntryRef and
163 /// its optional_none_tag to keep it the size of a single pointer.
164 template <>
166  : public clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef> {
167  using StorageImpl =
169 
170 public:
171  OptionalStorage() = default;
172 
173  template <class... ArgTypes>
174  explicit OptionalStorage(std::in_place_t, ArgTypes &&...Args)
175  : StorageImpl(std::in_place_t{}, std::forward<ArgTypes>(Args)...) {}
176 
178  StorageImpl::operator=(Ref);
179  return *this;
180  }
181 };
182 
183 static_assert(sizeof(OptionalDirectoryEntryRef) == sizeof(DirectoryEntryRef),
184  "OptionalDirectoryEntryRef must avoid size overhead");
185 
186 static_assert(std::is_trivially_copyable<OptionalDirectoryEntryRef>::value,
187  "OptionalDirectoryEntryRef should be trivially copyable");
188 
189 } // end namespace optional_detail
190 } // namespace clang
191 
192 namespace llvm {
193 
194 template <> struct PointerLikeTypeTraits<clang::DirectoryEntryRef> {
195  static inline void *getAsVoidPointer(clang::DirectoryEntryRef Dir) {
196  return const_cast<clang::DirectoryEntryRef::MapEntry *>(&Dir.getMapEntry());
197  }
198 
199  static inline clang::DirectoryEntryRef getFromVoidPointer(void *Ptr) {
201  *reinterpret_cast<const clang::DirectoryEntryRef::MapEntry *>(Ptr));
202  }
203 
204  static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<
205  const clang::DirectoryEntryRef::MapEntry *>::NumLowBitsAvailable;
206 };
207 
208 /// Specialisation of DenseMapInfo for DirectoryEntryRef.
209 template <> struct DenseMapInfo<clang::DirectoryEntryRef> {
212  clang::DirectoryEntryRef::dense_map_empty_tag());
213  }
214 
217  clang::DirectoryEntryRef::dense_map_tombstone_tag());
218  }
219 
220  static unsigned getHashValue(clang::DirectoryEntryRef Val) {
221  return hash_value(Val);
222  }
223 
226  // Catch the easy cases: both empty, both tombstone, or the same ref.
227  if (LHS.isSameRef(RHS))
228  return true;
229 
230  // Confirm LHS and RHS are valid.
231  if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey())
232  return false;
233 
234  // It's safe to use operator==.
235  return LHS == RHS;
236  }
237 };
238 
239 } // end namespace llvm
240 
241 #endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
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
const MapEntry & getMapEntry() const
friend llvm::hash_code hash_value(DirectoryEntryRef Ref)
Hash code is based on the DirectoryEntry, not the specific named reference.
const DirectoryEntry & getDirEntry() const
bool isSameRef(DirectoryEntryRef RHS) const
Check if RHS referenced the file in exactly the same way.
Cached information about one directory (either on disk or in the virtual file system).
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)
OptionalStorage & operator=(clang::DirectoryEntryRef Ref)
Code completion in a.
The JSON file list parser is used to communicate input to InstallAPI.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
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)