Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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