1 //===--- Ownership.h - Parser Ownership Helpers -----------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains classes for managing ownership of Stmt and Expr nodes.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_PARSE_OWNERSHIP_H
15 #define LLVM_CLANG_PARSE_OWNERSHIP_H
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/PointerIntPair.h"
20 //===----------------------------------------------------------------------===//
22 //===----------------------------------------------------------------------===//
27 /// OpaquePtr - This is a very simple POD type that wraps a pointer that the
28 /// Parser doesn't know about but that Sema or another client does. The UID
29 /// template argument is used to make sure that "Decl" pointers are not
30 /// compatible with "Type" pointers for example.
35 OpaquePtr() : Ptr(0) {}
39 return llvm::PointerLikeTypeTraits<T*>::getFromVoidPointer(Ptr);
44 return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer(Ptr);
47 void *get() const { return Ptr; }
50 static OpaquePtr make(T P) {
51 OpaquePtr R; R.set(P); return R;
56 Ptr = llvm::PointerLikeTypeTraits<T>::getAsVoidPointer(P);
59 operator bool() const { return Ptr != 0; }
65 class PointerLikeTypeTraits<clang::OpaquePtr<UID> > {
67 static inline void *getAsVoidPointer(clang::OpaquePtr<UID> P) {
68 // FIXME: Doesn't work? return P.getAs< void >();
71 static inline clang::OpaquePtr<UID> getFromVoidPointer(void *P) {
72 return clang::OpaquePtr<UID>::make(P);
74 enum { NumLowBitsAvailable = 3 };
80 // -------------------------- About Move Emulation -------------------------- //
81 // The smart pointer classes in this file attempt to emulate move semantics
82 // as they appear in C++0x with rvalue references. Since C++03 doesn't have
83 // rvalue references, some tricks are needed to get similar results.
84 // Move semantics in C++0x have the following properties:
85 // 1) "Moving" means transferring the value of an object to another object,
86 // similar to copying, but without caring what happens to the old object.
87 // In particular, this means that the new object can steal the old object's
88 // resources instead of creating a copy.
89 // 2) Since moving can modify the source object, it must either be explicitly
90 // requested by the user, or the modifications must be unnoticeable.
91 // 3) As such, C++0x moving is only allowed in three contexts:
92 // * By explicitly using std::move() to request it.
93 // * From a temporary object, since that object cannot be accessed
94 // afterwards anyway, thus making the state unobservable.
95 // * On function return, since the object is not observable afterwards.
97 // To sum up: moving from a named object should only be possible with an
98 // explicit std::move(), or on function return. Moving from a temporary should
99 // be implicitly done. Moving from a const object is forbidden.
101 // The emulation is not perfect, and has the following shortcomings:
102 // * move() is not in namespace std.
103 // * move() is required on function return.
104 // * There are difficulties with implicit conversions.
105 // * Microsoft's compiler must be given the /Za switch to successfully compile.
107 // -------------------------- Implementation -------------------------------- //
108 // The move emulation relies on the peculiar reference binding semantics of
109 // C++03: as a rule, a non-const reference may not bind to a temporary object,
110 // except for the implicit object parameter in a member function call, which
111 // can refer to a temporary even when not being const.
112 // The moveable object has five important functions to facilitate moving:
113 // * A private, unimplemented constructor taking a non-const reference to its
114 // own class. This constructor serves a two-fold purpose.
115 // - It prevents the creation of a copy constructor that takes a const
116 // reference. Temporaries would be able to bind to the argument of such a
117 // constructor, and that would be bad.
118 // - Named objects will bind to the non-const reference, but since it's
119 // private, this will fail to compile. This prevents implicit moving from
121 // There's also a copy assignment operator for the same purpose.
122 // * An implicit, non-const conversion operator to a special mover type. This
123 // type represents the rvalue reference of C++0x. Being a non-const member,
124 // its implicit this parameter can bind to temporaries.
125 // * A constructor that takes an object of this mover type. This constructor
126 // performs the actual move operation. There is an equivalent assignment
128 // There is also a free move() function that takes a non-const reference to
129 // an object and returns a temporary. Internally, this function uses explicit
130 // constructor calls to move the value from the referenced object to the return
133 // There are now three possible scenarios of use.
134 // * Copying from a const object. Constructor overload resolution will find the
135 // non-const copy constructor, and the move constructor. The first is not
136 // viable because the const object cannot be bound to the non-const reference.
137 // The second fails because the conversion to the mover object is non-const.
138 // Moving from a const object fails as intended.
139 // * Copying from a named object. Constructor overload resolution will select
140 // the non-const copy constructor, but fail as intended, because this
141 // constructor is private.
142 // * Copying from a temporary. Constructor overload resolution cannot select
143 // the non-const copy constructor, because the temporary cannot be bound to
144 // the non-const reference. It thus selects the move constructor. The
145 // temporary can be bound to the implicit this parameter of the conversion
146 // operator, because of the special binding rule. Construction succeeds.
147 // Note that the Microsoft compiler, as an extension, allows binding
148 // temporaries against non-const references. The compiler thus selects the
149 // non-const copy constructor and fails, because the constructor is private.
150 // Passing /Za (disable extensions) disables this behaviour.
151 // The free move() function is used to move from a named object.
153 // Note that when passing an object of a different type (the classes below
154 // have OwningResult and OwningPtr, which should be mixable), you get a problem.
155 // Argument passing and function return use copy initialization rules. The
156 // effect of this is that, when the source object is not already of the target
157 // type, the compiler will first seek a way to convert the source object to the
158 // target type, and only then attempt to copy the resulting object. This means
159 // that when passing an OwningResult where an OwningPtr is expected, the
160 // compiler will first seek a conversion from OwningResult to OwningPtr, then
161 // copy the OwningPtr. The resulting conversion sequence is:
162 // OwningResult object -> ResultMover -> OwningResult argument to
163 // OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr
164 // This conversion sequence is too complex to be allowed. Thus the special
165 // move_* functions, which help the compiler out with some explicit
168 // Flip this switch to measure performance impact of the smart pointers.
169 //#define DISABLE_SMART_POINTERS
173 class PointerLikeTypeTraits<clang::ActionBase*> {
174 typedef clang::ActionBase* PT;
176 static inline void *getAsVoidPointer(PT P) { return P; }
177 static inline PT getFromVoidPointer(void *P) {
178 return static_cast<PT>(P);
180 enum { NumLowBitsAvailable = 2 };
186 class DiagnosticBuilder;
188 // Determines whether the low bit of the result pointer for the
189 // given UID is always zero. If so, ActionResult will use that bit
190 // for it's "invalid" flag.
191 template<unsigned UID>
192 struct IsResultPtrLowBitFree {
193 static const bool value = false;
196 /// ActionBase - A small part split from Action because of the horrible
197 /// definition order dependencies between Action and the smart pointers.
200 /// Out-of-line virtual destructor to provide home for this class.
201 virtual ~ActionBase();
203 // Types - Though these don't actually enforce strong typing, they document
204 // what types are required to be identical for the actions.
205 typedef OpaquePtr<0> DeclPtrTy;
206 typedef OpaquePtr<1> DeclGroupPtrTy;
207 typedef OpaquePtr<2> TemplateTy;
210 typedef void MemInitTy;
213 typedef void TemplateParamsTy;
214 typedef void CXXScopeTy;
215 typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr<N>.
217 /// ActionResult - This structure is used while parsing/acting on
218 /// expressions, stmts, etc. It encapsulates both the object returned by
219 /// the action, plus a sense of whether or not it is valid.
220 /// When CompressInvalid is true, the "invalid" flag will be
221 /// stored in the low bit of the Val pointer.
222 template<unsigned UID,
223 typename PtrTy = void*,
224 bool CompressInvalid = IsResultPtrLowBitFree<UID>::value>
230 ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {}
231 template<typename ActualExprTy>
232 ActionResult(ActualExprTy val) : Val(val), Invalid(false) {}
233 ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
235 PtrTy get() const { return Val; }
236 void set(PtrTy V) { Val = V; }
237 bool isInvalid() const { return Invalid; }
239 const ActionResult &operator=(PtrTy RHS) {
246 // This ActionResult partial specialization places the "invalid"
247 // flag into the low bit of the pointer.
248 template<unsigned UID, typename PtrTy>
249 class ActionResult<UID, PtrTy, true> {
250 // A pointer whose low bit is 1 if this result is invalid, 0
252 uintptr_t PtrWithInvalid;
253 typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
255 ActionResult(bool Invalid = false)
256 : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
258 template<typename ActualExprTy>
259 ActionResult(ActualExprTy *val) {
261 void *VP = PtrTraits::getAsVoidPointer(V);
262 PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
263 assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
266 ActionResult(PtrTy V) {
267 void *VP = PtrTraits::getAsVoidPointer(V);
268 PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
269 assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
272 ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
275 void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
276 return PtrTraits::getFromVoidPointer(VP);
280 void *VP = PtrTraits::getAsVoidPointer(V);
281 PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
282 assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
285 bool isInvalid() const { return PtrWithInvalid & 0x01; }
287 const ActionResult &operator=(PtrTy RHS) {
288 void *VP = PtrTraits::getAsVoidPointer(RHS);
289 PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
290 assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
295 /// Deletion callbacks - Since the parser doesn't know the concrete types of
296 /// the AST nodes being generated, it must do callbacks to delete objects
297 /// when recovering from errors. These are in ActionBase because the smart
298 /// pointers need access to them.
299 virtual void DeleteExpr(ExprTy *E) {}
300 virtual void DeleteStmt(StmtTy *S) {}
301 virtual void DeleteTemplateParams(TemplateParamsTy *P) {}
304 /// ASTDestroyer - The type of an AST node destruction function pointer.
305 typedef void (ActionBase::*ASTDestroyer)(void *);
307 /// For the transition phase: translate from an ASTDestroyer to its
308 /// ActionResult UID.
309 template <ASTDestroyer Destroyer> struct DestroyerToUID;
310 template <> struct DestroyerToUID<&ActionBase::DeleteExpr> {
311 static const unsigned UID = 0;
313 template <> struct DestroyerToUID<&ActionBase::DeleteStmt> {
314 static const unsigned UID = 1;
316 /// ASTOwningResult - A moveable smart pointer for AST nodes that also
317 /// has an extra flag to indicate an additional success status.
318 template <ASTDestroyer Destroyer> class ASTOwningResult;
320 /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns
321 /// the individual pointers, not the array holding them.
322 template <ASTDestroyer Destroyer> class ASTMultiPtr;
324 #if !defined(DISABLE_SMART_POINTERS)
326 /// Move emulation helper for ASTOwningResult. NEVER EVER use this class
327 /// directly if you don't know what you're doing.
328 template <ASTDestroyer Destroyer>
331 ASTOwningResult<Destroyer> &Moved;
334 ASTResultMover(ASTOwningResult<Destroyer> &moved) : Moved(moved) {}
336 ASTOwningResult<Destroyer> * operator ->() { return &Moved; }
339 /// Move emulation helper for ASTMultiPtr. NEVER EVER use this class
340 /// directly if you don't know what you're doing.
341 template <ASTDestroyer Destroyer>
344 ASTMultiPtr<Destroyer> &Moved;
347 ASTMultiMover(ASTMultiPtr<Destroyer> &moved) : Moved(moved) {}
349 ASTMultiPtr<Destroyer> * operator ->() { return &Moved; }
351 /// Reset the moved object's internal structures.
357 /// Kept only as a type-safe wrapper for a void pointer, when smart pointers
358 /// are disabled. When they are enabled, ASTOwningResult takes over.
359 template <ASTDestroyer Destroyer>
365 explicit ASTOwningPtr(ActionBase &) : Node(0) {}
366 ASTOwningPtr(ActionBase &, void *node) : Node(node) {}
367 // Normal copying operators are defined implicitly.
368 ASTOwningPtr(const ASTOwningResult<Destroyer> &o);
370 ASTOwningPtr & operator =(void *raw) {
375 /// Access to the raw pointer.
376 void * get() const { return Node; }
378 /// Release the raw pointer.
383 /// Take outside ownership of the raw pointer and cast it down.
386 return static_cast<T*>(Node);
389 /// Alias for interface familiarity with unique_ptr.
396 // Important: There are two different implementations of
397 // ASTOwningResult below, depending on whether
398 // DISABLE_SMART_POINTERS is defined. If you make changes that
399 // affect the interface, be sure to compile and test both ways!
401 #if !defined(DISABLE_SMART_POINTERS)
402 template <ASTDestroyer Destroyer>
403 class ASTOwningResult
405 llvm::PointerIntPair<ActionBase*, 1, bool> ActionInv;
408 friend class moving::ASTResultMover<Destroyer>;
410 ASTOwningResult(ASTOwningResult&); // DO NOT IMPLEMENT
411 ASTOwningResult& operator =(ASTOwningResult&); // DO NOT IMPLEMENT
415 assert(ActionInv.getPointer() &&
416 "Smart pointer has node but no action.");
417 (ActionInv.getPointer()->*Destroyer)(Ptr);
423 typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
425 explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
426 : ActionInv(&actions, invalid), Ptr(0) {}
427 ASTOwningResult(ActionBase &actions, void *node)
428 : ActionInv(&actions, false), Ptr(node) {}
429 ASTOwningResult(ActionBase &actions, const DumbResult &res)
430 : ActionInv(&actions, res.isInvalid()), Ptr(res.get()) {}
431 /// Move from another owning result
432 ASTOwningResult(moving::ASTResultMover<Destroyer> mover)
433 : ActionInv(mover->ActionInv),
442 /// Move assignment from another owning result
443 ASTOwningResult &operator=(moving::ASTResultMover<Destroyer> mover) {
445 ActionInv = mover->ActionInv;
451 /// Assignment from a raw pointer. Takes ownership - beware!
452 ASTOwningResult &operator=(void *raw) {
455 ActionInv.setInt(false);
459 /// Assignment from an ActionResult. Takes ownership - beware!
460 ASTOwningResult &operator=(const DumbResult &res) {
463 ActionInv.setInt(res.isInvalid());
467 /// Access to the raw pointer.
468 void *get() const { return Ptr; }
470 bool isInvalid() const { return ActionInv.getInt(); }
472 /// Does this point to a usable AST node? To be usable, the node must be
473 /// valid and non-null.
474 bool isUsable() const { return !isInvalid() && get(); }
476 /// Take outside ownership of the raw pointer.
485 /// Take outside ownership of the raw pointer and cast it down.
488 return static_cast<T*>(take());
491 /// Alias for interface familiarity with unique_ptr.
492 void *release() { return take(); }
494 /// Pass ownership to a classical ActionResult.
495 DumbResult result() {
502 operator moving::ASTResultMover<Destroyer>() {
503 return moving::ASTResultMover<Destroyer>(*this);
507 template <ASTDestroyer Destroyer>
508 class ASTOwningResult
511 typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
517 explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
518 : Result(invalid) { }
519 ASTOwningResult(ActionBase &actions, void *node) : Result(node) { }
520 ASTOwningResult(ActionBase &actions, const DumbResult &res) : Result(res) { }
521 // Normal copying semantics are defined implicitly.
522 ASTOwningResult(const ASTOwningPtr<Destroyer> &o) : Result(o.get()) { }
524 /// Assignment from a raw pointer. Takes ownership - beware!
525 ASTOwningResult & operator =(void *raw)
531 /// Assignment from an ActionResult. Takes ownership - beware!
532 ASTOwningResult & operator =(const DumbResult &res) {
537 /// Access to the raw pointer.
538 void * get() const { return Result.get(); }
540 bool isInvalid() const { return Result.isInvalid(); }
542 /// Does this point to a usable AST node? To be usable, the node must be
543 /// valid and non-null.
544 bool isUsable() const { return !Result.isInvalid() && get(); }
546 /// Take outside ownership of the raw pointer.
551 /// Take outside ownership of the raw pointer and cast it down.
554 return static_cast<T*>(take());
557 /// Alias for interface familiarity with unique_ptr.
558 void * release() { return take(); }
560 /// Pass ownership to a classical ActionResult.
561 DumbResult result() { return Result; }
565 template <ASTDestroyer Destroyer>
568 #if !defined(DISABLE_SMART_POINTERS)
574 #if !defined(DISABLE_SMART_POINTERS)
575 friend class moving::ASTMultiMover<Destroyer>;
577 #if defined(_MSC_VER)
578 // Last tested with Visual Studio 2008.
579 // Visual C++ appears to have a bug where it does not recognise
580 // the return value from ASTMultiMover<Destroyer>::opeator-> as
581 // being a pointer to ASTMultiPtr. However, the diagnostics
582 // suggest it has the right name, simply that the pointer type
583 // is not convertible to itself.
584 // Either way, a classic C-style hard cast resolves any issue.
585 static ASTMultiPtr* hack(moving::ASTMultiMover<Destroyer> & source) {
586 return (ASTMultiPtr*)source.operator->();
590 ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT
591 // Reference member prevents copy assignment.
594 assert((Count == 0 || Nodes) && "No nodes when count is not zero.");
595 for (unsigned i = 0; i < Count; ++i) {
597 (Actions.*Destroyer)(Nodes[i]);
603 #if !defined(DISABLE_SMART_POINTERS)
604 explicit ASTMultiPtr(ActionBase &actions)
605 : Actions(actions), Nodes(0), Count(0) {}
606 ASTMultiPtr(ActionBase &actions, void **nodes, unsigned count)
607 : Actions(actions), Nodes(nodes), Count(count) {}
609 ASTMultiPtr(moving::ASTMultiMover<Destroyer> mover)
610 #if defined(_MSC_VER)
611 // Apply the visual C++ hack supplied above.
612 // Last tested with Visual Studio 2008.
613 : Actions(hack(mover)->Actions), Nodes(hack(mover)->Nodes), Count(hack(mover)->Count) {
615 : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) {
620 // Normal copying implicitly defined
621 explicit ASTMultiPtr(ActionBase &) : Nodes(0), Count(0) {}
622 ASTMultiPtr(ActionBase &, void **nodes, unsigned count)
623 : Nodes(nodes), Count(count) {}
624 // Fake mover in Parse/AstGuard.h needs this:
625 ASTMultiPtr(void **nodes, unsigned count) : Nodes(nodes), Count(count) {}
628 #if !defined(DISABLE_SMART_POINTERS)
630 ASTMultiPtr & operator =(moving::ASTMultiMover<Destroyer> mover) {
632 Nodes = mover->Nodes;
633 Count = mover->Count;
639 /// Access to the raw pointers.
640 void ** get() const { return Nodes; }
642 /// Access to the count.
643 unsigned size() const { return Count; }
646 #if !defined(DISABLE_SMART_POINTERS)
656 #if !defined(DISABLE_SMART_POINTERS)
658 operator moving::ASTMultiMover<Destroyer>() {
659 return moving::ASTMultiMover<Destroyer>(*this);
664 class ASTTemplateArgsPtr {
665 #if !defined(DISABLE_SMART_POINTERS)
670 mutable unsigned Count;
672 #if !defined(DISABLE_SMART_POINTERS)
677 for (unsigned i = 0; i != Count; ++i)
678 if (Args[i] && !ArgIsType[i])
679 Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]);
686 ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType,
688 #if !defined(DISABLE_SMART_POINTERS)
691 Args(args), ArgIsType(argIsType), Count(count) { }
693 // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
694 ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) :
695 #if !defined(DISABLE_SMART_POINTERS)
696 Actions(Other.Actions),
698 Args(Other.Args), ArgIsType(Other.ArgIsType), Count(Other.Count) {
699 #if !defined(DISABLE_SMART_POINTERS)
704 // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
705 ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) {
706 #if !defined(DISABLE_SMART_POINTERS)
707 Actions = Other.Actions;
710 ArgIsType = Other.ArgIsType;
712 #if !defined(DISABLE_SMART_POINTERS)
718 #if !defined(DISABLE_SMART_POINTERS)
719 ~ASTTemplateArgsPtr() { destroy(); }
722 void **getArgs() const { return Args; }
723 bool *getArgIsType() const {return ArgIsType; }
724 unsigned size() const { return Count; }
726 void reset(void **args, bool *argIsType, unsigned count) {
727 #if !defined(DISABLE_SMART_POINTERS)
731 ArgIsType = argIsType;
735 void *operator[](unsigned Arg) const { return Args[Arg]; }
737 void **release() const {
738 #if !defined(DISABLE_SMART_POINTERS)
745 /// \brief A small vector that owns a set of AST nodes.
746 template <ASTDestroyer Destroyer, unsigned N = 8>
747 class ASTOwningVector : public llvm::SmallVector<void *, N> {
748 #if !defined(DISABLE_SMART_POINTERS)
753 ASTOwningVector(ASTOwningVector &); // do not implement
754 ASTOwningVector &operator=(ASTOwningVector &); // do not implement
757 explicit ASTOwningVector(ActionBase &Actions)
758 #if !defined(DISABLE_SMART_POINTERS)
759 : Actions(Actions), Owned(true)
763 #if !defined(DISABLE_SMART_POINTERS)
768 for (unsigned I = 0, Last = this->size(); I != Last; ++I)
769 (Actions.*Destroyer)((*this)[I]);
774 #if !defined(DISABLE_SMART_POINTERS)
777 return &this->front();
780 template<typename T> T **takeAs() { return (T**)take(); }
782 #if !defined(DISABLE_SMART_POINTERS)
783 ActionBase &getActions() const { return Actions; }
787 /// A SmallVector of statements, with stack size 32 (as that is the only one
789 typedef ASTOwningVector<&ActionBase::DeleteStmt, 32> StmtVector;
790 /// A SmallVector of expressions, with stack size 12 (the maximum used.)
791 typedef ASTOwningVector<&ActionBase::DeleteExpr, 12> ExprVector;
793 template <ASTDestroyer Destroyer, unsigned N> inline
794 ASTMultiPtr<Destroyer> move_arg(ASTOwningVector<Destroyer, N> &vec) {
795 #if !defined(DISABLE_SMART_POINTERS)
796 return ASTMultiPtr<Destroyer>(vec.getActions(), vec.take(), vec.size());
798 return ASTMultiPtr<Destroyer>(vec.take(), vec.size());
802 #if !defined(DISABLE_SMART_POINTERS)
804 // Out-of-line implementations due to definition dependencies
806 template <ASTDestroyer Destroyer> inline
807 void moving::ASTMultiMover<Destroyer>::release() {
814 template <ASTDestroyer Destroyer> inline
815 ASTOwningResult<Destroyer> move(ASTOwningResult<Destroyer> &ptr) {
816 return ASTOwningResult<Destroyer>(moving::ASTResultMover<Destroyer>(ptr));
819 template <ASTDestroyer Destroyer> inline
820 ASTMultiPtr<Destroyer> move(ASTMultiPtr<Destroyer> &ptr) {
821 return ASTMultiPtr<Destroyer>(moving::ASTMultiMover<Destroyer>(ptr));
826 template <ASTDestroyer Destroyer> inline
827 ASTOwningPtr<Destroyer>::ASTOwningPtr(const ASTOwningResult<Destroyer> &o)
831 // These versions are hopefully no-ops.
832 template <ASTDestroyer Destroyer> inline
833 ASTOwningResult<Destroyer>& move(ASTOwningResult<Destroyer> &ptr) {
837 template <ASTDestroyer Destroyer> inline
838 ASTOwningPtr<Destroyer>& move(ASTOwningPtr<Destroyer> &ptr) {
842 template <ASTDestroyer Destroyer> inline
843 ASTMultiPtr<Destroyer>& move(ASTMultiPtr<Destroyer> &ptr) {