Coverage Report

Created: 2021-01-23 06:44

/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
9.36M
  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.5M
  const DirectoryEntry &getDirEntry() const { return *ME->getValue(); }
48
49
413k
  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
19.4k
  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
9.87M
  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
73.1k
  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
117k
  DirectoryEntryRef(optional_none_tag) : ME(nullptr) {}
92
1.04M
  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
7.60M
  MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::MapEntryOptionalStorage()
Line
Count
Source
120
7.48M
  MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::MapEntryOptionalStorage()
Line
Count
Source
120
117k
  MapEntryOptionalStorage() : MaybeRef(optional_none_tag()) {}
121
122
  template <class... ArgTypes>
123
  explicit MapEntryOptionalStorage(llvm::optional_detail::in_place_t,
124
                                   ArgTypes &&...Args)
125
9.69M
      : MaybeRef(std::forward<ArgTypes>(Args)...) {}
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::MapEntryOptionalStorage<clang::DirectoryEntryRef const&>(llvm::optional_detail::in_place_t, clang::DirectoryEntryRef const&)
Line
Count
Source
125
2.17M
      : MaybeRef(std::forward<ArgTypes>(Args)...) {}
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::MapEntryOptionalStorage<clang::FileEntryRef>(llvm::optional_detail::in_place_t, clang::FileEntryRef&&)
Line
Count
Source
125
2.48M
      : MaybeRef(std::forward<ArgTypes>(Args)...) {}
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::MapEntryOptionalStorage<clang::DirectoryEntryRef>(llvm::optional_detail::in_place_t, clang::DirectoryEntryRef&&)
Line
Count
Source
125
180k
      : MaybeRef(std::forward<ArgTypes>(Args)...) {}
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::MapEntryOptionalStorage<clang::FileEntryRef const&>(llvm::optional_detail::in_place_t, clang::FileEntryRef const&)
Line
Count
Source
125
4.86M
      : MaybeRef(std::forward<ArgTypes>(Args)...) {}
126
127
  void reset() { MaybeRef = optional_none_tag(); }
128
129
118M
  bool hasValue() const { return MaybeRef.hasOptionalValue(); }
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::hasValue() const
Line
Count
Source
129
1.04M
  bool hasValue() const { return MaybeRef.hasOptionalValue(); }
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::hasValue() const
Line
Count
Source
129
117M
  bool hasValue() const { return MaybeRef.hasOptionalValue(); }
130
131
19.5M
  RefTy &getValue() LLVM_LVALUE_FUNCTION {
132
19.5M
    assert(hasValue());
133
19.5M
    return MaybeRef;
134
19.5M
  }
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::getValue() &
Line
Count
Source
131
18.8M
  RefTy &getValue() LLVM_LVALUE_FUNCTION {
132
18.8M
    assert(hasValue());
133
18.8M
    return MaybeRef;
134
18.8M
  }
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::getValue() &
Line
Count
Source
131
638k
  RefTy &getValue() LLVM_LVALUE_FUNCTION {
132
638k
    assert(hasValue());
133
638k
    return MaybeRef;
134
638k
  }
135
71.3M
  RefTy const &getValue() const LLVM_LVALUE_FUNCTION {
136
71.3M
    assert(hasValue());
137
71.3M
    return MaybeRef;
138
71.3M
  }
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::getValue() const &
Line
Count
Source
135
44.2k
  RefTy const &getValue() const LLVM_LVALUE_FUNCTION {
136
44.2k
    assert(hasValue());
137
44.2k
    return MaybeRef;
138
44.2k
  }
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::getValue() const &
Line
Count
Source
135
71.3M
  RefTy const &getValue() const LLVM_LVALUE_FUNCTION {
136
71.3M
    assert(hasValue());
137
71.3M
    return MaybeRef;
138
71.3M
  }
139
#if LLVM_HAS_RVALUE_REFERENCE_THIS
140
  RefTy &&getValue() && {
141
    assert(hasValue());
142
    return std::move(MaybeRef);
143
  }
144
#endif
145
146
  template <class... Args> void emplace(Args &&...args) {
147
    MaybeRef = RefTy(std::forward<Args>(args)...);
148
  }
149
150
1.75M
  MapEntryOptionalStorage &operator=(RefTy Ref) {
151
1.75M
    MaybeRef = Ref;
152
1.75M
    return *this;
153
1.75M
  }
clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>::operator=(clang::DirectoryEntryRef)
Line
Count
Source
150
19.4k
  MapEntryOptionalStorage &operator=(RefTy Ref) {
151
19.4k
    MaybeRef = Ref;
152
19.4k
    return *this;
153
19.4k
  }
clang::FileMgr::MapEntryOptionalStorage<clang::FileEntryRef>::operator=(clang::FileEntryRef)
Line
Count
Source
150
1.73M
  MapEntryOptionalStorage &operator=(RefTy Ref) {
151
1.73M
    MaybeRef = Ref;
152
1.73M
    return *this;
153
1.73M
  }
154
};
155
156
} // end namespace FileMgr
157
} // end namespace clang
158
159
namespace llvm {
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 <>
165
class OptionalStorage<clang::DirectoryEntryRef>
166
    : public clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef> {
167
  using StorageImpl =
168
      clang::FileMgr::MapEntryOptionalStorage<clang::DirectoryEntryRef>;
169
170
public:
171
117k
  OptionalStorage() = default;
172
173
  template <class... ArgTypes>
174
  explicit OptionalStorage(in_place_t, ArgTypes &&...Args)
175
2.35M
      : StorageImpl(in_place_t{}, std::forward<ArgTypes>(Args)...) {}
llvm::optional_detail::OptionalStorage<clang::DirectoryEntryRef, true>::OptionalStorage<clang::DirectoryEntryRef const&>(llvm::optional_detail::in_place_t, clang::DirectoryEntryRef const&)
Line
Count
Source
175
2.17M
      : StorageImpl(in_place_t{}, std::forward<ArgTypes>(Args)...) {}
llvm::optional_detail::OptionalStorage<clang::DirectoryEntryRef, true>::OptionalStorage<clang::DirectoryEntryRef>(llvm::optional_detail::in_place_t, clang::DirectoryEntryRef&&)
Line
Count
Source
175
180k
      : StorageImpl(in_place_t{}, std::forward<ArgTypes>(Args)...) {}
176
177
19.4k
  OptionalStorage &operator=(clang::DirectoryEntryRef Ref) {
178
19.4k
    StorageImpl::operator=(Ref);
179
19.4k
    return *this;
180
19.4k
  }
181
};
182
183
static_assert(sizeof(Optional<clang::DirectoryEntryRef>) ==
184
                  sizeof(clang::DirectoryEntryRef),
185
              "Optional<DirectoryEntryRef> must avoid size overhead");
186
187
static_assert(
188
    std::is_trivially_copyable<Optional<clang::DirectoryEntryRef>>::value,
189
    "Optional<DirectoryEntryRef> should be trivially copyable");
190
191
} // end namespace optional_detail
192
193
/// Specialisation of DenseMapInfo for DirectoryEntryRef.
194
template <> struct DenseMapInfo<clang::DirectoryEntryRef> {
195
  static inline clang::DirectoryEntryRef getEmptyKey() {
196
    return clang::DirectoryEntryRef(
197
        clang::DirectoryEntryRef::dense_map_empty_tag());
198
  }
199
200
  static inline clang::DirectoryEntryRef getTombstoneKey() {
201
    return clang::DirectoryEntryRef(
202
        clang::DirectoryEntryRef::dense_map_tombstone_tag());
203
  }
204
205
  static unsigned getHashValue(clang::DirectoryEntryRef Val) {
206
    return hash_value(Val);
207
  }
208
209
  static bool isEqual(clang::DirectoryEntryRef LHS,
210
                      clang::DirectoryEntryRef RHS) {
211
    // Catch the easy cases: both empty, both tombstone, or the same ref.
212
    if (LHS.isSameRef(RHS))
213
      return true;
214
215
    // Confirm LHS and RHS are valid.
216
    if (LHS.isSpecialDenseMapKey() || RHS.isSpecialDenseMapKey())
217
      return false;
218
219
    // It's safe to use operator==.
220
    return LHS == RHS;
221
  }
222
};
223
224
} // end namespace llvm
225
226
namespace clang {
227
228
/// Wrapper around Optional<DirectoryEntryRef> that degrades to 'const
229
/// DirectoryEntry*', facilitating incremental patches to propagate
230
/// DirectoryEntryRef.
231
///
232
/// This class can be used as return value or field where it's convenient for
233
/// an Optional<DirectoryEntryRef> to degrade to a 'const DirectoryEntry*'. The
234
/// purpose is to avoid code churn due to dances like the following:
235
/// \code
236
/// // Old code.
237
/// lvalue = rvalue;
238
///
239
/// // Temporary code from an incremental patch.
240
/// Optional<DirectoryEntryRef> MaybeF = rvalue;
241
/// lvalue = MaybeF ? &MaybeF.getDirectoryEntry() : nullptr;
242
///
243
/// // Final code.
244
/// lvalue = rvalue;
245
/// \endcode
246
///
247
/// FIXME: Once DirectoryEntryRef is "everywhere" and DirectoryEntry::LastRef
248
/// and DirectoryEntry::getName have been deleted, delete this class and
249
/// replace instances with Optional<DirectoryEntryRef>.
250
class OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr
251
    : public Optional<DirectoryEntryRef> {
252
public:
253
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr() = default;
254
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
255
      OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
256
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(
257
      const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
258
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
259
  operator=(OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &&) = default;
260
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
261
  operator=(const OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &) = default;
262
263
32.0k
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(llvm::NoneType) {}
264
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(DirectoryEntryRef Ref)
265
58.6k
      : Optional<DirectoryEntryRef>(Ref) {}
266
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr(Optional<DirectoryEntryRef> MaybeRef)
267
0
      : Optional<DirectoryEntryRef>(MaybeRef) {}
268
269
0
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(llvm::NoneType) {
270
0
    Optional<DirectoryEntryRef>::operator=(None);
271
0
    return *this;
272
0
  }
273
0
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &operator=(DirectoryEntryRef Ref) {
274
0
    Optional<DirectoryEntryRef>::operator=(Ref);
275
0
    return *this;
276
0
  }
277
  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr &
278
0
  operator=(Optional<DirectoryEntryRef> MaybeRef) {
279
0
    Optional<DirectoryEntryRef>::operator=(MaybeRef);
280
0
    return *this;
281
0
  }
282
283
  /// Degrade to 'const DirectoryEntry *' to allow  DirectoryEntry::LastRef and
284
  /// DirectoryEntry::getName have been deleted, delete this class and replace
285
  /// instances with Optional<DirectoryEntryRef>
286
234
  operator const DirectoryEntry *() const {
287
234
    return hasValue() ? &getValue().getDirEntry() : 
nullptr0
;
288
234
  }
289
};
290
291
static_assert(std::is_trivially_copyable<
292
                  OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr>::value,
293
              "OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr should be "
294
              "trivially copyable");
295
296
} // end namespace clang
297
298
#endif // LLVM_CLANG_BASIC_DIRECTORYENTRY_H