Coverage Report

Created: 2021-08-24 07:12

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