Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Basic/DirectoryEntry.h
Line
Count
Source (jump to first uncovered line)
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).
34
class DirectoryEntry {
35
507k
  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
5.85M
  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.
50
class DirectoryEntryRef {
51
public:
52
10.4M
  const DirectoryEntry &getDirEntry() const { return *ME->getValue(); }
53
54
9.29M
  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
9.50M
  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
2.33M
  operator const DirectoryEntry *() const { return &getDirEntry(); }
90
91
private:
92
  friend class FileMgr::MapEntryOptionalStorage<DirectoryEntryRef>;
93
  struct optional_none_tag {};
94
95
  // Private constructor for use by OptionalStorage.
96
1.41M
  DirectoryEntryRef(optional_none_tag) : ME(nullptr) {}
97
20.2M
  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
12.5M
  MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::MapEntryOptionalStorage()
Line
Count
Source
125
11.1M
  MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::MapEntryOptionalStorage()
Line
Count
Source
125
1.41M
  MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
126
127
  template <class... ArgTypes>
128
  explicit MapEntryOptionalStorage(llvm::in_place_t, ArgTypes &&...Args)
129
28.5M
      : MaybeRef(std::forward<ArgTypes>(Args)...) {}
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::MapEntryOptionalStorage<clang::DirectoryEntryRef const&>(llvm::in_place_t, clang::DirectoryEntryRef const&)
Line
Count
Source
129
11.9M
      : MaybeRef(std::forward<ArgTypes>(Args)...) {}
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::MapEntryOptionalStorage<clang::FileEntryRef>(llvm::in_place_t, clang::FileEntryRef&&)
Line
Count
Source
129
4.21M
      : MaybeRef(std::forward<ArgTypes>(Args)...) {}
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::MapEntryOptionalStorage<clang::DirectoryEntryRef>(llvm::in_place_t, clang::DirectoryEntryRef&&)
Line
Count
Source
129
5.51M
      : MaybeRef(std::forward<ArgTypes>(Args)...) {}
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::MapEntryOptionalStorage<clang::FileEntryRef const&>(llvm::in_place_t, clang::FileEntryRef const&)
Line
Count
Source
129
6.94M
      : MaybeRef(std::forward<ArgTypes>(Args)...) {}
130
131
  void reset() { MaybeRef = optional_none_tag(); }
132
133
217M
  bool has_value() const { return MaybeRef.hasOptionalValue(); }
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::has_value() const
Line
Count
Source
133
20.2M
  bool has_value() const { return MaybeRef.hasOptionalValue(); }
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::has_value() const
Line
Count
Source
133
197M
  bool has_value() const { return MaybeRef.hasOptionalValue(); }
134
  bool hasValue() const { return MaybeRef.hasOptionalValue(); }
135
136
43.1M
  RefTy &value() & {
137
43.1M
    assert(has_value());
138
0
    return MaybeRef;
139
43.1M
  }
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::value() &
Line
Count
Source
136
32.5M
  RefTy &value() & {
137
32.5M
    assert(has_value());
138
0
    return MaybeRef;
139
32.5M
  }
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::value() &
Line
Count
Source
136
10.5M
  RefTy &value() & {
137
10.5M
    assert(has_value());
138
0
    return MaybeRef;
139
10.5M
  }
140
  RefTy &getValue() & {
141
    assert(has_value());
142
    return MaybeRef;
143
  }
144
122M
  RefTy const &value() const & {
145
122M
    assert(has_value());
146
0
    return MaybeRef;
147
122M
  }
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::value() const &
Line
Count
Source
144
694k
  RefTy const &value() const & {
145
694k
    assert(has_value());
146
0
    return MaybeRef;
147
694k
  }
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::value() const &
Line
Count
Source
144
122M
  RefTy const &value() const & {
145
122M
    assert(has_value());
146
0
    return MaybeRef;
147
122M
  }
148
  RefTy const &getValue() const & {
149
    assert(has_value());
150
    return MaybeRef;
151
  }
152
  RefTy &&value() && {
153
    assert(has_value());
154
    return std::move(MaybeRef);
155
  }
156
  RefTy &&getValue() && {
157
    assert(has_value());
158
    return std::move(MaybeRef);
159
  }
160
161
  template <class... Args> void emplace(Args &&...args) {
162
    MaybeRef = RefTy(std::forward<Args>(args)...);
163
  }
164
165
2.83M
  MapEntryOptionalStorage &operator=(RefTy Ref) {
166
2.83M
    MaybeRef = Ref;
167
2.83M
    return *this;
168
2.83M
  }
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::operator=(clang::DirectoryEntryRef)
Line
Count
Source
165
35.3k
  MapEntryOptionalStorage &operator=(RefTy Ref) {
166
35.3k
    MaybeRef = Ref;
167
35.3k
    return *this;
168
35.3k
  }
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::operator=(clang::FileEntryRef)
Line
Count
Source
165
2.79M
  MapEntryOptionalStorage &operator=(RefTy Ref) {
166
2.79M
    MaybeRef = Ref;
167
2.79M
    return *this;
168
2.79M
  }
169
};
170
171
} // end namespace FileMgr
172
} // end namespace clang
173
174
namespace llvm {
175
namespace optional_detail {
176
177
/// Customize OptionalStorage<DirectoryEntryRef> to use DirectoryEntryRef and
178
/// its optional_none_tag to keep it the size of a single pointer.
179
template <>
180
class OptionalStorage<clang::DirectoryEntryRef>
181
    : public clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef> {
182
  using StorageImpl =
183
      clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>;
184
185
public:
186
1.41M
  OptionalStorage() = default;
187
188
  template <class... ArgTypes>
189
  explicit OptionalStorage(in_place_t, ArgTypes &&...Args)
190
17.4M
      : StorageImpl(in_place_t{}, std::forward<ArgTypes>(Args)...) {}
llvm::optional_detail::OptionalStorage<clang::DirectoryEntryRef, true>::OptionalStorage<clang::DirectoryEntryRef const&>(llvm::in_place_t, clang::DirectoryEntryRef const&)
Line
Count
Source
190
11.9M
      : StorageImpl(in_place_t{}, std::forward<ArgTypes>(Args)...) {}
llvm::optional_detail::OptionalStorage<clang::DirectoryEntryRef, true>::OptionalStorage<clang::DirectoryEntryRef>(llvm::in_place_t, clang::DirectoryEntryRef&&)
Line
Count
Source
190
5.51M
      : StorageImpl(in_place_t{}, std::forward<ArgTypes>(Args)...) {}
191
192
35.3k
  OptionalStorage &operator=(clang::DirectoryEntryRef Ref) {
193
35.3k
    StorageImpl::operator=(Ref);
194
35.3k
    return *this;
195
35.3k
  }
196
};
197
198
static_assert(sizeof(Optional<clang::DirectoryEntryRef>) ==
199
                  sizeof(clang::DirectoryEntryRef),
200
              "Optional<DirectoryEntryRef> must avoid size overhead");
201
202
static_assert(
203
    std::is_trivially_copyable<Optional<clang::DirectoryEntryRef>>::value,
204
    "Optional<DirectoryEntryRef> should be trivially copyable");
205
206
} // end namespace optional_detail
207
208
/// Specialisation of DenseMapInfo for DirectoryEntryRef.
209
template <> struct DenseMapInfo<clang::DirectoryEntryRef> {
210
  static inline clang::DirectoryEntryRef getEmptyKey() {
211
    return clang::DirectoryEntryRef(
212
        clang::DirectoryEntryRef::dense_map_empty_tag());
213
  }
214
215
  static inline clang::DirectoryEntryRef getTombstoneKey() {
216
    return clang::DirectoryEntryRef(
217
        clang::DirectoryEntryRef::dense_map_tombstone_tag());
218
  }
219
220
  static unsigned getHashValue(clang::DirectoryEntryRef Val) {
221
    return hash_value(Val);
222
  }
223
224
  static bool isEqual(clang::DirectoryEntryRef LHS,
225
                      clang::DirectoryEntryRef RHS) {
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
namespace clang {
242
243
/// Wrapper around Optional<DirectoryEntryRef> that degrades to 'const
244
/// DirectoryEntry*', facilitating incremental patches to propagate
245
/// DirectoryEntryRef.
246
///
247
/// This class can be used as return value or field where it's convenient for
248
/// an Optional<DirectoryEntryRef> to degrade to a 'const DirectoryEntry*'. The
249
/// purpose is to avoid code churn due to dances like the following:
250
/// \code
251
/// // Old code.
252
/// lvalue = rvalue;
253
///
254
/// // Temporary code from an incremental patch.
255
/// Optional<DirectoryEntryRef> MaybeF = rvalue;
256
/// lvalue = MaybeF ? &MaybeF.getDirectoryEntry() : nullptr;
257
///
258
/// // Final code.
259
/// lvalue = rvalue;
260
/// \endcode
261
///
262
/// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::LastRef
263
/// and DirectoryEntry::getName have been deleted, delete this class and
264
/// replace instances with Optional<DirectoryEntryRef>.
265
class OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr
266
    : public Optional<DirectoryEntryRef> {
267
public:
268
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr() = default;
269
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
270
      OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
271
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
272
      const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
273
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
274
  operator=(OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
275
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
276
  operator=(const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
277
278
0
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(llvm::NoneType) {}
279
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(DirectoryEntryRef Ref)
280
0
      : Optional<DirectoryEntryRef>(Ref) {}
281
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(Optional<DirectoryEntryRef> MaybeRef)
282
0
      : Optional<DirectoryEntryRef>(MaybeRef) {}
283
284
0
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(llvm::NoneType) {
285
0
    Optional<DirectoryEntryRef>::operator=(None);
286
0
    return *this;
287
0
  }
288
0
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(DirectoryEntryRef Ref) {
289
0
    Optional<DirectoryEntryRef>::operator=(Ref);
290
0
    return *this;
291
0
  }
292
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
293
0
  operator=(Optional<DirectoryEntryRef> MaybeRef) {
294
0
    Optional<DirectoryEntryRef>::operator=(MaybeRef);
295
0
    return *this;
296
0
  }
297
298
  /// Degrade to 'const DirectoryEntry *' to allow  DirectoryEntry::LastRef and
299
  /// DirectoryEntry::getName have been deleted, delete this class and replace
300
  /// instances with Optional<DirectoryEntryRef>
301
0
  operator const DirectoryEntry *() const {
302
0
    return has_value() ? &value().getDirEntry() : nullptr;
303
0
  }
304
};
305
306
static_assert(std::is_trivially_copyable<
307
                  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr>::value,
308
              "OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr should be "
309
              "trivially copyable");
310
311
} // end namespace clang
312
313
#endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H