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
29namespace clang {
30namespace FileMgr {
31
32template <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.
49public:
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
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
89private:
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
116namespace 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.
120template <class RefTy> class MapEntryOptionalStorage {
121 using optional_none_tag = typename RefTy::optional_none_tag;
122 RefTy MaybeRef;
123
124public:
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
160namespace 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.
164template <>
166 : public clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef> {
167 using StorageImpl =
169
170public:
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
183static_assert(sizeof(OptionalDirectoryEntryRef) == sizeof(DirectoryEntryRef),
184 "OptionalDirectoryEntryRef must avoid size overhead");
185
186static_assert(std::is_trivially_copyable<OptionalDirectoryEntryRef>::value,
187 "OptionalDirectoryEntryRef should be trivially copyable");
188
189} // end namespace optional_detail
190} // namespace clang
191
192namespace llvm {
193
194template <> struct PointerLikeTypeTraits<clang::DirectoryEntryRef> {
196 return const_cast<clang::DirectoryEntryRef::MapEntry *>(&Dir.getMapEntry());
197 }
198
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.
209template <> struct DenseMapInfo<clang::DirectoryEntryRef> {
212 clang::DirectoryEntryRef::dense_map_empty_tag());
213 }
214
217 clang::DirectoryEntryRef::dense_map_tombstone_tag());
218 }
219
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
friend llvm::hash_code hash_value(DirectoryEntryRef Ref)
Hash code is based on the DirectoryEntry, not the specific named reference.
bool isSameRef(DirectoryEntryRef RHS) const
Check if RHS referenced the file in exactly the same way.
const MapEntry & getMapEntry() const
const DirectoryEntry & getDirEntry() const
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.
CustomizableOptional< DirectoryEntryRef > OptionalDirectoryEntryRef
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)