]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - include/clang/Parse/Ownership.h
Import Clang r74788.
[FreeBSD/FreeBSD.git] / include / clang / Parse / Ownership.h
1 //===--- Ownership.h - Parser Ownership Helpers -----------------*- 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 contains classes for managing ownership of Stmt and Expr nodes.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_CLANG_PARSE_OWNERSHIP_H
15 #define LLVM_CLANG_PARSE_OWNERSHIP_H
16
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/PointerIntPair.h"
19
20 //===----------------------------------------------------------------------===//
21 // OpaquePtr
22 //===----------------------------------------------------------------------===//
23
24 namespace clang {
25   class ActionBase;
26   
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.
31   template<int UID>
32   class OpaquePtr {
33     void *Ptr;
34   public:
35     OpaquePtr() : Ptr(0) {}
36     
37     template <typename T>
38     T* getAs() const {
39       return llvm::PointerLikeTypeTraits<T*>::getFromVoidPointer(Ptr);
40     }
41     
42     template <typename T>
43     T getAsVal() const {
44       return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer(Ptr);
45     }
46     
47     void *get() const { return Ptr; }
48     
49     template<typename T>
50     static OpaquePtr make(T P) {
51       OpaquePtr R; R.set(P); return R;
52     }
53     
54     template<typename T>
55     void set(T P) {
56       Ptr = llvm::PointerLikeTypeTraits<T>::getAsVoidPointer(P);
57     }
58     
59     operator bool() const { return Ptr != 0; }
60   };
61 }
62
63 namespace llvm {
64   template <int UID>
65   class PointerLikeTypeTraits<clang::OpaquePtr<UID> > {
66   public:
67     static inline void *getAsVoidPointer(clang::OpaquePtr<UID> P) {
68       // FIXME: Doesn't work? return P.getAs< void >();
69       return P.get();
70     }
71     static inline clang::OpaquePtr<UID> getFromVoidPointer(void *P) {
72       return clang::OpaquePtr<UID>::make(P);
73     }
74     enum { NumLowBitsAvailable = 3 };
75   };
76 }
77
78
79
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.
96 //
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.
100 //
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.
106 //
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
120 //     named objects.
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
127 //   operator.
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
131 // value.
132 //
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.
152 //
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
166 // conversions.
167
168 // Flip this switch to measure performance impact of the smart pointers.
169 //#define DISABLE_SMART_POINTERS
170
171 namespace llvm {
172   template<>
173   class PointerLikeTypeTraits<clang::ActionBase*> {
174     typedef clang::ActionBase* PT;
175   public:
176     static inline void *getAsVoidPointer(PT P) { return P; }
177     static inline PT getFromVoidPointer(void *P) {
178       return static_cast<PT>(P);
179     }
180     enum { NumLowBitsAvailable = 2 };
181   };
182 }
183
184 namespace clang {
185   // Basic
186   class DiagnosticBuilder;
187
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;
194   };
195
196   /// ActionBase - A small part split from Action because of the horrible
197   /// definition order dependencies between Action and the smart pointers.
198   class ActionBase {
199   public:
200     /// Out-of-line virtual destructor to provide home for this class.
201     virtual ~ActionBase();
202
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;
208     typedef void AttrTy;
209     typedef void BaseTy;
210     typedef void MemInitTy;
211     typedef void ExprTy;
212     typedef void StmtTy;
213     typedef void TemplateParamsTy;
214     typedef void CXXScopeTy;
215     typedef void TypeTy;  // FIXME: Change TypeTy to use OpaquePtr<N>.
216
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>
225     class ActionResult {
226       PtrTy Val;
227       bool Invalid;
228
229     public:
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) {}
234
235       PtrTy get() const { return Val; }
236       void set(PtrTy V) { Val = V; }
237       bool isInvalid() const { return Invalid; }
238
239       const ActionResult &operator=(PtrTy RHS) {
240         Val = RHS;
241         Invalid = false;
242         return *this;
243       }
244     };
245
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
251       // otherwise.
252       uintptr_t PtrWithInvalid;
253       typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
254     public:
255       ActionResult(bool Invalid = false) 
256         : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
257
258       template<typename ActualExprTy>
259       ActionResult(ActualExprTy *val) {
260         PtrTy V(val);
261         void *VP = PtrTraits::getAsVoidPointer(V);
262         PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
263         assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
264       }
265       
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");
270       }
271       
272       ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
273
274       PtrTy get() const {
275         void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01); 
276         return PtrTraits::getFromVoidPointer(VP);
277       }
278
279       void set(PtrTy V) {
280         void *VP = PtrTraits::getAsVoidPointer(V);
281         PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
282         assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
283       }
284
285       bool isInvalid() const { return PtrWithInvalid & 0x01; }
286
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");
291         return *this;
292       }
293     };
294
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) {}
302   };
303
304   /// ASTDestroyer - The type of an AST node destruction function pointer.
305   typedef void (ActionBase::*ASTDestroyer)(void *);
306
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;
312   };
313   template <> struct DestroyerToUID<&ActionBase::DeleteStmt> {
314     static const unsigned UID = 1;
315   };
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;
319
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;
323
324 #if !defined(DISABLE_SMART_POINTERS)
325   namespace moving {
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>
329     class ASTResultMover
330     {
331       ASTOwningResult<Destroyer> &Moved;
332
333     public:
334       ASTResultMover(ASTOwningResult<Destroyer> &moved) : Moved(moved) {}
335
336       ASTOwningResult<Destroyer> * operator ->() { return &Moved; }
337     };
338
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>
342     class ASTMultiMover
343     {
344       ASTMultiPtr<Destroyer> &Moved;
345
346     public:
347       ASTMultiMover(ASTMultiPtr<Destroyer> &moved) : Moved(moved) {}
348
349       ASTMultiPtr<Destroyer> * operator ->() { return &Moved; }
350
351       /// Reset the moved object's internal structures.
352       void release();
353     };
354   }
355 #else
356
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>
360   class ASTOwningPtr
361   {
362     void *Node;
363
364   public:
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);
369
370     ASTOwningPtr & operator =(void *raw) {
371       Node = raw;
372       return *this;
373     }
374
375     /// Access to the raw pointer.
376     void * get() const { return Node; }
377
378     /// Release the raw pointer.
379     void * take() {
380       return Node;
381     }
382
383     /// Take outside ownership of the raw pointer and cast it down.
384     template<typename T>
385     T *takeAs() {
386       return static_cast<T*>(Node);
387     }
388
389     /// Alias for interface familiarity with unique_ptr.
390     void * release() {
391       return take();
392     }
393   };
394 #endif
395
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!
400
401 #if !defined(DISABLE_SMART_POINTERS)
402   template <ASTDestroyer Destroyer>
403   class ASTOwningResult
404   {
405     llvm::PointerIntPair<ActionBase*, 1, bool> ActionInv;
406     void *Ptr;
407
408     friend class moving::ASTResultMover<Destroyer>;
409
410     ASTOwningResult(ASTOwningResult&); // DO NOT IMPLEMENT
411     ASTOwningResult& operator =(ASTOwningResult&); // DO NOT IMPLEMENT
412
413     void destroy() {
414       if (Ptr) {
415         assert(ActionInv.getPointer() &&
416                "Smart pointer has node but no action.");
417         (ActionInv.getPointer()->*Destroyer)(Ptr);
418         Ptr = 0;
419       }
420     }
421
422   public:
423     typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
424
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),
434         Ptr(mover->Ptr) {
435       mover->Ptr = 0;
436     }
437
438     ~ASTOwningResult() {
439       destroy();
440     }
441
442     /// Move assignment from another owning result
443     ASTOwningResult &operator=(moving::ASTResultMover<Destroyer> mover) {
444       destroy();
445       ActionInv = mover->ActionInv;
446       Ptr = mover->Ptr;
447       mover->Ptr = 0;
448       return *this;
449     }
450
451     /// Assignment from a raw pointer. Takes ownership - beware!
452     ASTOwningResult &operator=(void *raw) {
453       destroy();
454       Ptr = raw;
455       ActionInv.setInt(false);
456       return *this;
457     }
458
459     /// Assignment from an ActionResult. Takes ownership - beware!
460     ASTOwningResult &operator=(const DumbResult &res) {
461       destroy();
462       Ptr = res.get();
463       ActionInv.setInt(res.isInvalid());
464       return *this;
465     }
466
467     /// Access to the raw pointer.
468     void *get() const { return Ptr; }
469
470     bool isInvalid() const { return ActionInv.getInt(); }
471
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(); }
475
476     /// Take outside ownership of the raw pointer.
477     void *take() {
478       if (isInvalid())
479         return 0;
480       void *tmp = Ptr;
481       Ptr = 0;
482       return tmp;
483     }
484
485     /// Take outside ownership of the raw pointer and cast it down.
486     template<typename T>
487     T *takeAs() {
488       return static_cast<T*>(take());
489     }
490
491     /// Alias for interface familiarity with unique_ptr.
492     void *release() { return take(); }
493
494     /// Pass ownership to a classical ActionResult.
495     DumbResult result() {
496       if (isInvalid())
497         return true;
498       return take();
499     }
500
501     /// Move hook
502     operator moving::ASTResultMover<Destroyer>() {
503       return moving::ASTResultMover<Destroyer>(*this);
504     }
505   };
506 #else
507   template <ASTDestroyer Destroyer>
508   class ASTOwningResult
509   {
510   public:
511     typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
512
513   private:
514     DumbResult Result;
515
516   public:
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()) { }
523
524     /// Assignment from a raw pointer. Takes ownership - beware!
525     ASTOwningResult & operator =(void *raw)
526     {
527       Result = raw;
528       return *this;
529     }
530
531     /// Assignment from an ActionResult. Takes ownership - beware!
532     ASTOwningResult & operator =(const DumbResult &res) {
533       Result = res;
534       return *this;
535     }
536
537     /// Access to the raw pointer.
538     void * get() const { return Result.get(); }
539
540     bool isInvalid() const { return Result.isInvalid(); }
541
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(); }
545
546     /// Take outside ownership of the raw pointer.
547     void * take() {
548       return Result.get();
549     }
550
551     /// Take outside ownership of the raw pointer and cast it down.
552     template<typename T>
553     T *takeAs() {
554       return static_cast<T*>(take());
555     }
556
557     /// Alias for interface familiarity with unique_ptr.
558     void * release() { return take(); }
559
560     /// Pass ownership to a classical ActionResult.
561     DumbResult result() { return Result; }
562   };
563 #endif
564
565   template <ASTDestroyer Destroyer>
566   class ASTMultiPtr
567   {
568 #if !defined(DISABLE_SMART_POINTERS)
569     ActionBase &Actions;
570 #endif
571     void **Nodes;
572     unsigned Count;
573
574 #if !defined(DISABLE_SMART_POINTERS)
575     friend class moving::ASTMultiMover<Destroyer>;
576
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->();
587         }
588 #endif
589
590     ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT
591     // Reference member prevents copy assignment.
592
593     void destroy() {
594       assert((Count == 0 || Nodes) && "No nodes when count is not zero.");
595       for (unsigned i = 0; i < Count; ++i) {
596         if (Nodes[i])
597           (Actions.*Destroyer)(Nodes[i]);
598       }
599     }
600 #endif
601
602   public:
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) {}
608     /// Move constructor
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) {
614 #else
615       : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) {
616 #endif
617       mover.release();
618     }
619 #else
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) {}
626 #endif
627
628 #if !defined(DISABLE_SMART_POINTERS)
629     /// Move assignment
630     ASTMultiPtr & operator =(moving::ASTMultiMover<Destroyer> mover) {
631       destroy();
632       Nodes = mover->Nodes;
633       Count = mover->Count;
634       mover.release();
635       return *this;
636     }
637 #endif
638
639     /// Access to the raw pointers.
640     void ** get() const { return Nodes; }
641
642     /// Access to the count.
643     unsigned size() const { return Count; }
644
645     void ** release() {
646 #if !defined(DISABLE_SMART_POINTERS)
647       void **tmp = Nodes;
648       Nodes = 0;
649       Count = 0;
650       return tmp;
651 #else
652       return Nodes;
653 #endif
654     }
655
656 #if !defined(DISABLE_SMART_POINTERS)
657     /// Move hook
658     operator moving::ASTMultiMover<Destroyer>() {
659       return moving::ASTMultiMover<Destroyer>(*this);
660     }
661 #endif
662   };
663   
664   class ASTTemplateArgsPtr {
665 #if !defined(DISABLE_SMART_POINTERS)
666     ActionBase &Actions;
667 #endif
668     void **Args;
669     bool *ArgIsType;
670     mutable unsigned Count;
671     
672 #if !defined(DISABLE_SMART_POINTERS)
673     void destroy() {
674       if (!Count)
675         return;
676
677       for (unsigned i = 0; i != Count; ++i)
678         if (Args[i] && !ArgIsType[i])
679           Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]);
680
681       Count = 0;
682     }
683 #endif
684
685   public:
686     ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType,
687                        unsigned count) : 
688 #if !defined(DISABLE_SMART_POINTERS)
689       Actions(actions), 
690 #endif
691       Args(args), ArgIsType(argIsType), Count(count) { }
692
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), 
697 #endif
698       Args(Other.Args), ArgIsType(Other.ArgIsType), Count(Other.Count) {
699 #if !defined(DISABLE_SMART_POINTERS)
700       Other.Count = 0;
701 #endif
702     }
703
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;
708 #endif
709       Args = Other.Args;
710       ArgIsType = Other.ArgIsType;
711       Count = Other.Count;
712 #if !defined(DISABLE_SMART_POINTERS)
713       Other.Count = 0;
714 #endif
715       return *this;
716     }
717
718 #if !defined(DISABLE_SMART_POINTERS)
719     ~ASTTemplateArgsPtr() { destroy(); }
720 #endif
721
722     void **getArgs() const { return Args; }
723     bool *getArgIsType() const {return ArgIsType; }
724     unsigned size() const { return Count; }
725
726     void reset(void **args, bool *argIsType, unsigned count) {
727 #if !defined(DISABLE_SMART_POINTERS)
728       destroy();
729 #endif
730       Args = args;
731       ArgIsType = argIsType;
732       Count = count;
733     }
734
735     void *operator[](unsigned Arg) const { return Args[Arg]; }
736
737     void **release() const { 
738 #if !defined(DISABLE_SMART_POINTERS)
739       Count = 0;
740 #endif
741       return Args;
742     }
743   };
744
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)
749     ActionBase &Actions;
750     bool Owned;
751 #endif
752
753     ASTOwningVector(ASTOwningVector &); // do not implement
754     ASTOwningVector &operator=(ASTOwningVector &); // do not implement
755
756   public:
757     explicit ASTOwningVector(ActionBase &Actions) 
758 #if !defined(DISABLE_SMART_POINTERS)
759       : Actions(Actions), Owned(true)
760 #endif
761     { }
762
763 #if !defined(DISABLE_SMART_POINTERS)
764     ~ASTOwningVector() {
765       if (!Owned)
766         return;
767
768       for (unsigned I = 0, Last = this->size(); I != Last; ++I)
769         (Actions.*Destroyer)((*this)[I]);
770     }
771 #endif
772
773     void **take() {
774 #if !defined(DISABLE_SMART_POINTERS)
775       Owned = false;
776 #endif
777       return &this->front();
778     }
779
780     template<typename T> T **takeAs() { return (T**)take(); }
781
782 #if !defined(DISABLE_SMART_POINTERS)
783     ActionBase &getActions() const { return Actions; }
784 #endif
785   };
786
787   /// A SmallVector of statements, with stack size 32 (as that is the only one
788   /// used.)
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;
792
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());
797 #else
798     return ASTMultiPtr<Destroyer>(vec.take(), vec.size());
799 #endif
800   }
801
802 #if !defined(DISABLE_SMART_POINTERS)
803
804   // Out-of-line implementations due to definition dependencies
805
806   template <ASTDestroyer Destroyer> inline
807   void moving::ASTMultiMover<Destroyer>::release() {
808     Moved.Nodes = 0;
809     Moved.Count = 0;
810   }
811
812   // Move overloads.
813
814   template <ASTDestroyer Destroyer> inline
815   ASTOwningResult<Destroyer> move(ASTOwningResult<Destroyer> &ptr) {
816     return ASTOwningResult<Destroyer>(moving::ASTResultMover<Destroyer>(ptr));
817   }
818
819   template <ASTDestroyer Destroyer> inline
820   ASTMultiPtr<Destroyer> move(ASTMultiPtr<Destroyer> &ptr) {
821     return ASTMultiPtr<Destroyer>(moving::ASTMultiMover<Destroyer>(ptr));
822   }
823
824 #else
825
826   template <ASTDestroyer Destroyer> inline
827   ASTOwningPtr<Destroyer>::ASTOwningPtr(const ASTOwningResult<Destroyer> &o)
828     : Node(o.get())
829   {}
830
831   // These versions are hopefully no-ops.
832   template <ASTDestroyer Destroyer> inline
833   ASTOwningResult<Destroyer>& move(ASTOwningResult<Destroyer> &ptr) {
834     return ptr;
835   }
836
837   template <ASTDestroyer Destroyer> inline
838   ASTOwningPtr<Destroyer>& move(ASTOwningPtr<Destroyer> &ptr) {
839     return ptr;
840   }
841
842   template <ASTDestroyer Destroyer> inline
843   ASTMultiPtr<Destroyer>& move(ASTMultiPtr<Destroyer> &ptr) {
844     return ptr;
845   }
846 #endif
847 }
848
849 #endif