Introduce MaybeOwningPtr, a smart pointer that may (or may not) have
[oota-llvm.git] / include / llvm / ADT / OwningPtr.h
1 //===- llvm/ADT/OwningPtr.h - Smart ptr that owns the pointee ---*- 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 defines and implements the OwningPtr class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ADT_OWNING_PTR_H
15 #define LLVM_ADT_OWNING_PTR_H
16
17 #include <cassert>
18 #include <cstddef>
19
20 namespace llvm {
21
22 /// OwningPtr smart pointer - OwningPtr mimics a built-in pointer except that it
23 /// guarantees deletion of the object pointed to, either on destruction of the
24 /// OwningPtr or via an explicit reset().  Once created, ownership of the
25 /// pointee object can be taken away from OwningPtr by using the take method.
26 template<class T>
27 class OwningPtr {
28   OwningPtr(OwningPtr const &);             // DO NOT IMPLEMENT
29   OwningPtr &operator=(OwningPtr const &);  // DO NOT IMPLEMENT
30   T *Ptr;
31 public:
32   explicit OwningPtr(T *P = 0) : Ptr(P) {}
33
34   ~OwningPtr() {
35     delete Ptr;
36   }
37
38   /// reset - Change the current pointee to the specified pointer.  Note that
39   /// calling this with any pointer (including a null pointer) deletes the
40   /// current pointer.
41   void reset(T *P = 0) {
42     if (P == Ptr) return;
43     T *Tmp = Ptr;
44     Ptr = P;
45     delete Tmp;
46   }
47
48   /// take - Reset the owning pointer to null and return its pointer.  This does
49   /// not delete the pointer before returning it.
50   T *take() {
51     T *Tmp = Ptr;
52     Ptr = 0;
53     return Tmp;
54   }
55
56   T &operator*() const {
57     assert(Ptr && "Cannot dereference null pointer");
58     return *Ptr;
59   }
60
61   T *operator->() const { return Ptr; }
62   T *get() const { return Ptr; }
63   operator bool() const { return Ptr != 0; }
64   bool operator!() const { return Ptr == 0; }
65
66   void swap(OwningPtr &RHS) {
67     T *Tmp = RHS.Ptr;
68     RHS.Ptr = Ptr;
69     Ptr = Tmp;
70   }
71 };
72
73 template<class T>
74 inline void swap(OwningPtr<T> &a, OwningPtr<T> &b) {
75   a.swap(b);
76 }
77
78 /// OwningArrayPtr smart pointer - OwningArrayPtr provides the same
79 ///  functionality as OwningPtr, except that it works for array types.
80 template<class T>
81 class OwningArrayPtr {
82   OwningArrayPtr(OwningArrayPtr const &);            // DO NOT IMPLEMENT
83   OwningArrayPtr &operator=(OwningArrayPtr const &); // DO NOT IMPLEMENT
84   T *Ptr;
85 public:
86   explicit OwningArrayPtr(T *P = 0) : Ptr(P) {}
87
88   ~OwningArrayPtr() {
89     delete [] Ptr;
90   }
91
92   /// reset - Change the current pointee to the specified pointer.  Note that
93   /// calling this with any pointer (including a null pointer) deletes the
94   /// current pointer.
95   void reset(T *P = 0) {
96     if (P == Ptr) return;
97     T *Tmp = Ptr;
98     Ptr = P;
99     delete [] Tmp;
100   }
101
102   /// take - Reset the owning pointer to null and return its pointer.  This does
103   /// not delete the pointer before returning it.
104   T *take() {
105     T *Tmp = Ptr;
106     Ptr = 0;
107     return Tmp;
108   }
109
110   T &operator[](std::ptrdiff_t i) const {
111     assert(Ptr && "Cannot dereference null pointer");
112     return Ptr[i];
113   }
114
115   T *get() const { return Ptr; }
116   operator bool() const { return Ptr != 0; }
117   bool operator!() const { return Ptr == 0; }
118
119   void swap(OwningArrayPtr &RHS) {
120     T *Tmp = RHS.Ptr;
121     RHS.Ptr = Ptr;
122     Ptr = Tmp;
123   }
124 };
125
126 template<class T>
127 inline void swap(OwningArrayPtr<T> &a, OwningArrayPtr<T> &b) {
128   a.swap(b);
129 }
130
131 /// \brief A smart pointer that may own the object it points to.
132 ///
133 /// An instance of \c MaybeOwningPtr may own the object it points to. If so,
134 /// it will guarantee that the object will be deleted either on destructin of
135 /// the OwningPtr or via an explicit reset(). Once created, ownership of the
136 /// pointee object can be taken away from OwningPtr by using the \c take()
137 /// method.
138 template<class T>
139 class MaybeOwningPtr {
140   T *Ptr;
141   bool Owned;
142   
143   struct MaybeOwningPtrRef {
144     MaybeOwningPtrRef(T *Ptr, bool &Owned) : Ptr(Ptr), Owned(Owned) { }
145     
146     T *Ptr;
147     bool &Owned;
148   };
149   
150 public:
151   MaybeOwningPtr() : Ptr(0), Owned(false) { }
152   
153   explicit MaybeOwningPtr(T *P, bool OwnP) : Ptr(P), Owned(OwnP) {}
154   
155   /// \brief Take ownership of the pointer stored in \c Other.
156   MaybeOwningPtr(MaybeOwningPtr& Other) : Ptr(Other.Ptr), Owned(Other.Owned) {
157     Other.Owned = false;
158   }
159
160   MaybeOwningPtr(MaybeOwningPtrRef Other) : Ptr(Other.Ptr), Owned(Other.Owned) {
161     Other.Owned = false;
162   }
163     
164   /// \brief Take ownership of the ppinter stored in \c Other.
165   MaybeOwningPtr &operator=(MaybeOwningPtr &Other) {
166     reset(Other.Ptr, Other.Owned);
167     Other.Owned = false;
168     return *this;
169   }
170
171   ~MaybeOwningPtr() {
172     if (Owned)
173       delete Ptr;
174   }
175   
176   operator MaybeOwningPtrRef() { return MaybeOwningPtrRef(Ptr, Owned); }
177   
178   /// reset - Change the current pointee to the specified pointer.  Note that
179   /// calling this with any pointer (including a null pointer) deletes the
180   /// current pointer.
181   void reset(T *P, bool OwnP) {
182     assert(P != Ptr);
183     if (Owned)
184       delete Ptr;
185     
186     Ptr = P;
187     Owned = OwnP;
188   }
189   
190   /// take - Return the underlying pointer and take ownership of it. This
191   /// \c MaybeOwningPtr must have ownership before the call, and will 
192   /// relinquish ownership as part of the call.
193   T *take() {
194     assert(Owned && "Cannot take ownership from a non-owning pointer");
195     Owned = false;
196     return Ptr;
197   }
198   
199   T &operator*() const {
200     assert(Ptr && "Cannot dereference null pointer");
201     return *Ptr;
202   }
203   
204   T *operator->() const { return Ptr; }
205   T *get() const { return Ptr; }
206   operator bool() const { return Ptr != 0; }
207   bool operator!() const { return Ptr == 0; }
208   
209   void swap(MaybeOwningPtr &RHS) {
210     T *Tmp = RHS.Ptr;
211     RHS.Ptr = Ptr;
212     Ptr = Tmp;
213     bool TmpOwned = RHS.Owned;
214     RHS.Owned = Owned;
215     Owned = TmpOwned;
216   }
217 };
218
219 template<class T>
220 inline void swap(MaybeOwningPtr<T> &a, MaybeOwningPtr<T> &b) {
221   a.swap(b);
222 }
223   
224 } // end namespace llvm
225
226 #endif