klee
Ref.h
Go to the documentation of this file.
1//===-- Ref.h ---------------------------------------------------*- C++ -*-===//
2//
3// The KLEE Symbolic Virtual Machine
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
29#ifndef KLEE_REF_H
30#define KLEE_REF_H
31
33
34#include <cassert>
35
36namespace llvm {
37 class raw_ostream;
38} // namespace llvm
39
40namespace klee {
41
42template<class T>
43class ref;
44
47 template<class T>
48 friend class ref;
49
51 unsigned refCount = 0;
52
53public:
54 ReferenceCounter() = default;
55 ~ReferenceCounter() = default;
56
57 // Explicitly initialise reference counter with 0 again
58 // As this object is part of another object, the copy-constructor
59 // might be invoked as part of the other one.
61
64 unsigned getCount() {return refCount;}
65
66 // Copy assignment operator
68 if (this == &a)
69 return *this;
70 // The new copy won't be referenced
71 refCount = 0;
72 return *this;
73 }
74
75 // Do not allow move operations for the reference counter
76 // as otherwise, references become incorrect.
77 ReferenceCounter(ReferenceCounter &&r) noexcept = delete;
78 ReferenceCounter &operator=(ReferenceCounter &&other) noexcept = delete;
79};
80
81template<class T>
82class ref {
83 T *ptr;
84
85public:
86 // default constructor: create a NULL reference
87 ref() : ptr(nullptr) {}
88 ~ref () { dec (); }
89
90private:
91 void inc() const {
92 if (ptr)
93 ++ptr->_refCount.refCount;
94 }
95
96 void dec() const {
97 if (ptr && --ptr->_refCount.refCount == 0)
98 delete ptr;
99 }
100
101public:
102 template<class U> friend class ref;
103
104 // constructor from pointer
105 ref(T *p) : ptr(p) {
106 inc();
107 }
108
109 // normal copy constructor
110 ref(const ref<T> &r) : ptr(r.ptr) {
111 inc();
112 }
113
114 // conversion constructor
115 template<class U>
116 ref (const ref<U> &r) : ptr(r.ptr) {
117 inc();
118 }
119
120 // normal move constructor: invoke the move assignment operator
121 ref(ref<T> &&r) noexcept : ptr(nullptr) { *this = std::move(r); }
122
123 // conversion move constructors: invoke the move assignment operator
124 template <class U> ref(ref<U> &&r) noexcept : ptr(nullptr) {
125 *this = std::move(r);
126 }
127
128 // pointer operations
129 T *get () const {
130 return ptr;
131 }
132
133 /* The copy assignment operator must also explicitly be defined,
134 * despite a redundant template. */
136 r.inc();
137 // Create a copy of the pointer as the
138 // referenced object might get destroyed by the following dec(),
139 // like in the following example:
140 // ````````````````````````
141 // Expr {
142 // ref<Expr> next;
143 // }
144 //
145 // ref<Expr> root;
146 // root = root->next;
147 // ````````````````````````
148 T *saved_ptr = r.ptr;
149 dec();
150 ptr = saved_ptr;
151
152 return *this;
153 }
154
155 template<class U> ref<T> &operator= (const ref<U> &r) {
156 r.inc();
157 // Create a copy of the pointer as the currently
158 // referenced object might get destroyed by the following dec(),
159 // like in the following example:
160 // ````````````````````````
161 // Expr {
162 // ref<Expr> next;
163 // }
164 //
165 // ref<Expr> root;
166 // root = root->next;
167 // ````````````````````````
168
169 U *saved_ptr = r.ptr;
170 dec();
171 ptr = saved_ptr;
172
173 return *this;
174 }
175
176 // Move assignment operator
177 ref<T> &operator=(ref<T> &&r) noexcept {
178 if (this == &r)
179 return *this;
180 dec();
181 ptr = r.ptr;
182 r.ptr = nullptr;
183 return *this;
184 }
185
186 // Move assignment operator
187 template <class U> ref<T> &operator=(ref<U> &&r) noexcept {
188 if (static_cast<void *>(this) == static_cast<void *>(&r))
189 return *this;
190
191 // Do not swap as the types might be not compatible
192 // Decrement local counter to not hold reference anymore
193 dec();
194
195 // Assign to this ref
196 ptr = cast_or_null<T>(r.ptr);
197
198 // Invalidate old ptr
199 r.ptr = nullptr;
200
201 // Return this pointer
202 return *this;
203 }
204
205 T& operator*() const {
206 return *ptr;
207 }
208
209 T* operator->() const {
210 return ptr;
211 }
212
213 bool isNull() const { return ptr == nullptr; }
214 explicit operator bool() const noexcept { return !isNull(); }
215
216 // assumes non-null arguments
217 int compare(const ref &rhs) const {
218 assert(!isNull() && !rhs.isNull() && "Invalid call to compare()");
219 return get()->compare(*rhs.get());
220 }
221
222 // assumes non-null arguments
223 bool operator<(const ref &rhs) const { return compare(rhs)<0; }
224 bool operator==(const ref &rhs) const { return compare(rhs)==0; }
225 bool operator!=(const ref &rhs) const { return compare(rhs)!=0; }
226};
227
228template<class T>
229inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const ref<T> &e) {
230 os << *e;
231 return os;
232}
233
234template<class T>
235inline std::stringstream &operator<<(std::stringstream &os, const ref<T> &e) {
236 os << *e;
237 return os;
238}
239
240} // end namespace klee
241
242namespace llvm {
243// simplify_type implementation for ref<>, which allows dyn_cast on a
244// ref<> to apply to the wrapper type. Conceptually the result of such a
245// dyn_cast should probably be a ref of the casted type, which historically
246// was breaking the idiom of initializing a variable to the result of a dyn_cast
247// inside an if condition, as ref<> did not have an operator bool() with isNull
248// semantics.
249template<typename T>
250struct simplify_type<const ::klee::ref<T> > {
251 using SimpleType = T *;
252 static SimpleType getSimplifiedValue(const ::klee::ref<T> &Ref) {
253 return Ref.get();
254 }
255};
256
257template<typename T>
258struct simplify_type< ::klee::ref<T> >
259 : public simplify_type<const ::klee::ref<T> > {};
260} // namespace llvm
261
262#endif /* KLEE_REF_H */
Reference counter to be used as part of a ref-managed struct or class.
Definition: Ref.h:46
ReferenceCounter(const ReferenceCounter &)
Definition: Ref.h:60
unsigned getCount()
Definition: Ref.h:64
unsigned refCount
Count how often the object has been referenced.
Definition: Ref.h:51
ReferenceCounter & operator=(ReferenceCounter &&other) noexcept=delete
ReferenceCounter(ReferenceCounter &&r) noexcept=delete
ReferenceCounter & operator=(const ReferenceCounter &a)
Definition: Ref.h:67
Definition: Ref.h:82
void dec() const
Definition: Ref.h:96
ref(T *p)
Definition: Ref.h:105
int compare(const ref &rhs) const
Definition: Ref.h:217
T * operator->() const
Definition: Ref.h:209
T & operator*() const
Definition: Ref.h:205
ref(const ref< T > &r)
Definition: Ref.h:110
bool operator==(const ref &rhs) const
Definition: Ref.h:224
ref< T > & operator=(ref< T > &&r) noexcept
Definition: Ref.h:177
ref(ref< U > &&r) noexcept
Definition: Ref.h:124
ref(const ref< U > &r)
Definition: Ref.h:116
T * ptr
Definition: Ref.h:83
ref()
Definition: Ref.h:87
ref(ref< T > &&r) noexcept
Definition: Ref.h:121
bool operator!=(const ref &rhs) const
Definition: Ref.h:225
void inc() const
Definition: Ref.h:91
bool operator<(const ref &rhs) const
Definition: Ref.h:223
bool isNull() const
Definition: Ref.h:213
~ref()
Definition: Ref.h:88
ref< T > & operator=(const ref< T > &r)
Definition: Ref.h:135
ref< T > & operator=(ref< U > &&r) noexcept
Definition: Ref.h:187
T * get() const
Definition: Ref.h:129
Definition: main.cpp:291
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const MemoryMap &mm)
static SimpleType getSimplifiedValue(const ::klee::ref< T > &Ref)
Definition: Ref.h:252