Coverage Report

Created: 2026-01-16 08:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/keystone/llvm/include/llvm/ADT/Optional.h
Line
Count
Source
1
//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
//  This file provides Optional, a template class modeled in the spirit of
11
//  OCaml's 'opt' variant.  The idea is to strongly type whether or not
12
//  a value can be optional.
13
//
14
//===----------------------------------------------------------------------===//
15
16
#ifndef LLVM_ADT_OPTIONAL_H
17
#define LLVM_ADT_OPTIONAL_H
18
19
#include "llvm/ADT/None.h"
20
#include "llvm/Support/AlignOf.h"
21
#include "llvm/Support/Compiler.h"
22
#include <cassert>
23
#include <new>
24
#include <utility>
25
26
namespace llvm_ks {
27
28
template<typename T>
29
class Optional {
30
  AlignedCharArrayUnion<T> storage;
31
  bool hasVal;
32
public:
33
  typedef T value_type;
34
35
7.14k
  Optional(NoneType) : hasVal(false) {}
36
  explicit Optional() : hasVal(false) {}
37
  Optional(const T &y) : hasVal(true) {
38
    new (storage.buffer) T(y);
39
  }
40
640
  Optional(const Optional &O) : hasVal(O.hasVal) {
41
640
    if (hasVal)
42
0
      new (storage.buffer) T(*O);
43
640
  }
44
45
1.28k
  Optional(T &&y) : hasVal(true) {
46
1.28k
    new (storage.buffer) T(std::forward<T>(y));
47
1.28k
  }
48
  Optional(Optional<T> &&O) : hasVal(O) {
49
    if (O) {
50
      new (storage.buffer) T(std::move(*O));
51
      O.reset();
52
    }
53
  }
54
  Optional &operator=(T &&y) {
55
    if (hasVal)
56
      **this = std::move(y);
57
    else {
58
      new (storage.buffer) T(std::move(y));
59
      hasVal = true;
60
    }
61
    return *this;
62
  }
63
  Optional &operator=(Optional &&O) {
64
    if (!O)
65
      reset();
66
    else {
67
      *this = std::move(*O);
68
      O.reset();
69
    }
70
    return *this;
71
  }
72
73
  /// Create a new object by constructing it in place with the given arguments.
74
  template<typename ...ArgTypes>
75
  void emplace(ArgTypes &&...Args) {
76
    reset();
77
    hasVal = true;
78
    new (storage.buffer) T(std::forward<ArgTypes>(Args)...);
79
  }
80
81
  static inline Optional create(const T* y) {
82
    return y ? Optional(*y) : Optional();
83
  }
84
85
  // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
86
  // could be made more efficient by passing by value, possibly unifying them
87
  // with the rvalue versions above - but this could place a different set of
88
  // requirements (notably: the existence of a default ctor) when implemented
89
  // in that way. Careful SFINAE to avoid such pitfalls would be required.
90
  Optional &operator=(const T &y) {
91
    if (hasVal)
92
      **this = y;
93
    else {
94
      new (storage.buffer) T(y);
95
      hasVal = true;
96
    }
97
    return *this;
98
  }
99
100
  Optional &operator=(const Optional &O) {
101
    if (!O)
102
      reset();
103
    else
104
      *this = *O;
105
    return *this;
106
  }
107
108
9.06k
  void reset() {
109
9.06k
    if (hasVal) {
110
1.28k
      (**this).~T();
111
1.28k
      hasVal = false;
112
1.28k
    }
113
9.06k
  }
114
115
9.06k
  ~Optional() {
116
9.06k
    reset();
117
9.06k
  }
118
119
0
  const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); }
Unexecuted instantiation: llvm_ks::Optional<llvm_ks::MipsABIInfo>::getPointer() const
Unexecuted instantiation: llvm_ks::Optional<llvm_ks::MCFixupKind>::getPointer() const
120
1.28k
  T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); }
121
  const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
122
  T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
123
124
0
  explicit operator bool() const { return hasVal; }
125
7.14k
  bool hasValue() const { return hasVal; }
llvm_ks::Optional<llvm_ks::MCFixupKind>::hasValue() const
Line
Count
Source
125
7.14k
  bool hasValue() const { return hasVal; }
Unexecuted instantiation: llvm_ks::Optional<llvm_ks::MipsABIInfo>::hasValue() const
126
  const T* operator->() const { return getPointer(); }
127
  T* operator->() { return getPointer(); }
128
0
  const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
Unexecuted instantiation: llvm_ks::Optional<llvm_ks::MipsABIInfo>::operator*() const &
Unexecuted instantiation: llvm_ks::Optional<llvm_ks::MCFixupKind>::operator*() const &
129
1.28k
  T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
130
131
  template <typename U>
132
  LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
133
    return hasValue() ? getValue() : std::forward<U>(value);
134
  }
135
136
#if LLVM_HAS_RVALUE_REFERENCE_THIS
137
  T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
138
  T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
139
140
  template <typename U>
141
  T getValueOr(U &&value) && {
142
    return hasValue() ? std::move(getValue()) : std::forward<U>(value);
143
  }
144
#endif
145
};
146
147
template <typename T> struct isPodLike;
148
template <typename T> struct isPodLike<Optional<T> > {
149
  // An Optional<T> is pod-like if T is.
150
  static const bool value = isPodLike<T>::value;
151
};
152
153
/// \brief Poison comparison between two \c Optional objects. Clients needs to
154
/// explicitly compare the underlying values and account for empty \c Optional
155
/// objects.
156
///
157
/// This routine will never be defined. It returns \c void to help diagnose
158
/// errors at compile time.
159
template<typename T, typename U>
160
void operator==(const Optional<T> &X, const Optional<U> &Y);
161
162
template<typename T>
163
bool operator==(const Optional<T> &X, NoneType) {
164
  return !X.hasValue();
165
}
166
167
template<typename T>
168
bool operator==(NoneType, const Optional<T> &X) {
169
  return X == None;
170
}
171
172
template<typename T>
173
bool operator!=(const Optional<T> &X, NoneType) {
174
  return !(X == None);
175
}
176
177
template<typename T>
178
bool operator!=(NoneType, const Optional<T> &X) {
179
  return X != None;
180
}
181
/// \brief Poison comparison between two \c Optional objects. Clients needs to
182
/// explicitly compare the underlying values and account for empty \c Optional
183
/// objects.
184
///
185
/// This routine will never be defined. It returns \c void to help diagnose
186
/// errors at compile time.
187
template<typename T, typename U>
188
void operator!=(const Optional<T> &X, const Optional<U> &Y);
189
190
/// \brief Poison comparison between two \c Optional objects. Clients needs to
191
/// explicitly compare the underlying values and account for empty \c Optional
192
/// objects.
193
///
194
/// This routine will never be defined. It returns \c void to help diagnose
195
/// errors at compile time.
196
template<typename T, typename U>
197
void operator<(const Optional<T> &X, const Optional<U> &Y);
198
199
/// \brief Poison comparison between two \c Optional objects. Clients needs to
200
/// explicitly compare the underlying values and account for empty \c Optional
201
/// objects.
202
///
203
/// This routine will never be defined. It returns \c void to help diagnose
204
/// errors at compile time.
205
template<typename T, typename U>
206
void operator<=(const Optional<T> &X, const Optional<U> &Y);
207
208
/// \brief Poison comparison between two \c Optional objects. Clients needs to
209
/// explicitly compare the underlying values and account for empty \c Optional
210
/// objects.
211
///
212
/// This routine will never be defined. It returns \c void to help diagnose
213
/// errors at compile time.
214
template<typename T, typename U>
215
void operator>=(const Optional<T> &X, const Optional<U> &Y);
216
217
/// \brief Poison comparison between two \c Optional objects. Clients needs to
218
/// explicitly compare the underlying values and account for empty \c Optional
219
/// objects.
220
///
221
/// This routine will never be defined. It returns \c void to help diagnose
222
/// errors at compile time.
223
template<typename T, typename U>
224
void operator>(const Optional<T> &X, const Optional<U> &Y);
225
226
} // end llvm namespace
227
228
#endif