zcov: / include/clang/Parse/Ownership.h


Files: 1 Branches Taken: 67.3% 33 / 49
Generated: 2010-02-10 01:31 Branches Executed: 83.7% 41 / 49
Line Coverage: 95.5% 148 / 155


Programs: 71 Runs 108527


       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            33437:   class OpaquePtr {
      33                 :     void *Ptr;
      34                 :   public:
      35          1580667:     OpaquePtr() : Ptr(0) {}
      36                 : 
      37                 :     template <typename T>
      38           280882:     T* getAs() const {
      39           280882:       return llvm::PointerLikeTypeTraits<T*>::getFromVoidPointer(Ptr);
      40                 :     }
      41                 : 
      42                 :     template <typename T>
      43            36009:     T getAsVal() const {
      44            36009:       return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer(Ptr);
      45                 :     }
      46                 : 
      47           165264:     void *get() const { return Ptr; }
      48                 : 
      49                 :     template<typename T>
      50           337802:     static OpaquePtr make(T P) {
      51           337802:       OpaquePtr R; R.set(P); return R;
      52                 :     }
      53                 : 
      54                 :     template<typename T>
      55           337802:     void set(T P) {
      56           337802:       Ptr = llvm::PointerLikeTypeTraits<T>::getAsVoidPointer(P);
      57           337802:     }
      58                 : 
      59            88440:     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           142008:     static inline void *getAsVoidPointer(clang::OpaquePtr<UID> P) {
      68                 :       // FIXME: Doesn't work? return P.getAs< void >();
      69           142008:       return P.get();
      70                 :     }
      71            60237:     static inline clang::OpaquePtr<UID> getFromVoidPointer(void *P) {
      72            60237:       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           422837:     static inline void *getAsVoidPointer(PT P) { return P; }
     177             4010:     static inline PT getFromVoidPointer(void *P) {
     178             4010:       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             2251:   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             7453:       ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {}
     231                 :       template<typename ActualExprTy>
     232            17369:       ActionResult(ActualExprTy val) : Val(val), Invalid(false) {}
     233                 :       ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
     234                 : 
     235            17485:       PtrTy get() const { return Val; }
     236                 :       void set(PtrTy V) { Val = V; }
     237            23966:       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             7233:       ActionResult(bool Invalid = false)
     256             7233:         : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
     257                 : 
     258                 :       template<typename ActualExprTy>
     259             3235:       ActionResult(ActualExprTy *val) {
     260             3235:         PtrTy V(val);
     261             3235:         void *VP = PtrTraits::getAsVoidPointer(V);
     262             3235:         PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
                        0: branch 0 not taken
                     1964: branch 1 taken
                        0: branch 3 not taken
                      958: branch 4 taken
                        0: branch 6 not taken
                        7: branch 7 taken
                        0: branch 9 not taken
                       20: branch 10 taken
                        0: branch 12 not taken
                       40: branch 13 taken
                        0: branch 15 not taken
                       30: branch 16 taken
                        0: branch 18 not taken
                      216: branch 19 taken
     263             3235:         assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
     264             3235:       }
     265                 : 
     266             1607:       ActionResult(PtrTy V) {
     267             1607:         void *VP = PtrTraits::getAsVoidPointer(V);
     268             1607:         PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
                        0: branch 0 not taken
                     1607: branch 1 taken
     269             1607:         assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
     270             1607:       }
     271                 : 
     272               12:       ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
     273                 : 
     274            16458:       PtrTy get() const {
     275            16458:         void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
     276            16458:         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            10505:       bool isInvalid() const { return PtrWithInvalid & 0x01; }
     286                 : 
     287             6653:       const ActionResult &operator=(PtrTy RHS) {
     288             6653:         void *VP = PtrTraits::getAsVoidPointer(RHS);
     289             6653:         PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
                        0: branch 0 not taken
                     6653: branch 1 taken
     290             6653:         assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
     291             6653:         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                1:     virtual void DeleteExpr(ExprTy *E) {}
     300                0:     virtual void DeleteStmt(StmtTy *S) {}
     301                0:     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                 :       ASTOwningResult<Destroyer> &Moved;
     331                 : 
     332                 :     public:
     333          2771589:       ASTResultMover(ASTOwningResult<Destroyer> &moved) : Moved(moved) {}
     334                 : 
     335          8314767:       ASTOwningResult<Destroyer> * operator ->() { return &Moved; }
     336                 :     };
     337                 : 
     338                 :     /// Move emulation helper for ASTMultiPtr. NEVER EVER use this class
     339                 :     /// directly if you don't know what you're doing.
     340                 :     template <ASTDestroyer Destroyer>
     341                 :     class ASTMultiMover {
     342                 :       ASTMultiPtr<Destroyer> &Moved;
     343                 : 
     344                 :     public:
     345           214005:       ASTMultiMover(ASTMultiPtr<Destroyer> &moved) : Moved(moved) {}
     346                 : 
     347           642015:       ASTMultiPtr<Destroyer> * operator ->() { return &Moved; }
     348                 : 
     349                 :       /// Reset the moved object's internal structures.
     350                 :       void release();
     351                 :     };
     352                 :   }
     353                 : #else
     354                 : 
     355                 :   /// Kept only as a type-safe wrapper for a void pointer, when smart pointers
     356                 :   /// are disabled. When they are enabled, ASTOwningResult takes over.
     357                 :   template <ASTDestroyer Destroyer>
     358                 :   class ASTOwningPtr {
     359                 :     void *Node;
     360                 : 
     361                 :   public:
     362                 :     explicit ASTOwningPtr(ActionBase &) : Node(0) {}
     363                 :     ASTOwningPtr(ActionBase &, void *node) : Node(node) {}
     364                 :     // Normal copying operators are defined implicitly.
     365                 :     ASTOwningPtr(const ASTOwningResult<Destroyer> &o);
     366                 : 
     367                 :     ASTOwningPtr & operator =(void *raw) {
     368                 :       Node = raw;
     369                 :       return *this;
     370                 :     }
     371                 : 
     372                 :     /// Access to the raw pointer.
     373                 :     void * get() const { return Node; }
     374                 : 
     375                 :     /// Release the raw pointer.
     376                 :     void * take() {
     377                 :       return Node;
     378                 :     }
     379                 : 
     380                 :     /// Take outside ownership of the raw pointer and cast it down.
     381                 :     template<typename T>
     382                 :     T *takeAs() {
     383                 :       return static_cast<T*>(Node);
     384                 :     }
     385                 : 
     386                 :     /// Alias for interface familiarity with unique_ptr.
     387                 :     void * release() {
     388                 :       return take();
     389                 :     }
     390                 :   };
     391                 : #endif
     392                 : 
     393                 :   // Important: There are two different implementations of
     394                 :   // ASTOwningResult below, depending on whether
     395                 :   // DISABLE_SMART_POINTERS is defined. If you make changes that
     396                 :   // affect the interface, be sure to compile and test both ways!
     397                 : 
     398                 : #if !defined(DISABLE_SMART_POINTERS)
     399                 :   template <ASTDestroyer Destroyer>
     400                 :   class ASTOwningResult {
     401                 :     llvm::PointerIntPair<ActionBase*, 1, bool> ActionInv;
     402                 :     void *Ptr;
     403                 : 
     404                 :     friend class moving::ASTResultMover<Destroyer>;
     405                 : 
     406                 :     ASTOwningResult(ASTOwningResult&); // DO NOT IMPLEMENT
     407                 :     ASTOwningResult& operator =(ASTOwningResult&); // DO NOT IMPLEMENT
     408                 : 
     409          3194591:     void destroy() {
                     2229: branch 0 taken
                  2851265: branch 1 taken
                       67: branch 2 taken
                   341612: branch 3 taken
     410          3194591:       if (Ptr) {
                     1938: branch 1 taken
                        0: branch 2 not taken
                        0: branch 6 not taken
                        0: branch 6 not taken
     411             2005:         assert(ActionInv.getPointer() &&
     412                 :                "Smart pointer has node but no action.");
     413             2005:         (ActionInv.getPointer()->*Destroyer)(Ptr);
     414             2005:         Ptr = 0;
     415                 :       }
     416          3194591:     }
     417                 : 
     418                 :   public:
     419                 :     typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
     420                 : 
     421           174147:     explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
     422           174147:       : ActionInv(&actions, invalid), Ptr(0) {}
     423           246695:     ASTOwningResult(ActionBase &actions, void *node)
     424           246695:       : ActionInv(&actions, false), Ptr(node) {}
     425             1995:     ASTOwningResult(ActionBase &actions, const DumbResult &res)
     426             1995:       : ActionInv(&actions, res.isInvalid()), Ptr(res.get()) {}
     427                 :     /// Move from another owning result
     428          2554367:     ASTOwningResult(moving::ASTResultMover<Destroyer> mover)
     429                 :       : ActionInv(mover->ActionInv),
     430          2554367:         Ptr(mover->Ptr) {
     431          2554367:       mover->Ptr = 0;
     432          2554367:     }
     433                 : 
     434          2977204:     ~ASTOwningResult() {
     435          2977204:       destroy();
     436          2977204:     }
     437                 : 
     438                 :     /// Move assignment from another owning result
     439           217222:     ASTOwningResult &operator=(moving::ASTResultMover<Destroyer> mover) {
     440           217222:       destroy();
     441           217222:       ActionInv = mover->ActionInv;
     442           217222:       Ptr = mover->Ptr;
     443           217222:       mover->Ptr = 0;
     444           217222:       return *this;
     445                 :     }
     446                 : 
     447                 :     /// Assignment from a raw pointer. Takes ownership - beware!
     448              165:     ASTOwningResult &operator=(void *raw) {
     449              165:       destroy();
     450              165:       Ptr = raw;
     451              165:       ActionInv.setInt(false);
     452              165:       return *this;
     453                 :     }
     454                 : 
     455                 :     /// Assignment from an ActionResult. Takes ownership - beware!
     456                0:     ASTOwningResult &operator=(const DumbResult &res) {
     457                0:       destroy();
     458                0:       Ptr = res.get();
     459                0:       ActionInv.setInt(res.isInvalid());
     460                0:       return *this;
     461                 :     }
     462                 : 
     463                 :     /// Access to the raw pointer.
     464           140714:     void *get() const { return Ptr; }
     465                 : 
     466           554989:     bool isInvalid() const { return ActionInv.getInt(); }
     467                 : 
     468                 :     /// Does this point to a usable AST node? To be usable, the node must be
     469                 :     /// valid and non-null.
                    21713: branch 1 taken
                      899: branch 2 taken
                    21471: branch 4 taken
                      242: branch 5 taken
     470            22612:     bool isUsable() const { return !isInvalid() && get(); }
     471                 : 
     472                 :     /// Take outside ownership of the raw pointer.
     473           231029:     void *take() {
                       73: branch 2 taken
                   193855: branch 4 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
     474           231029:       if (isInvalid())
     475              163:         return 0;
     476           230866:       void *tmp = Ptr;
     477           230866:       Ptr = 0;
     478           230866:       return tmp;
     479                 :     }
     480                 : 
     481                 :     /// Take outside ownership of the raw pointer and cast it down.
     482                 :     template<typename T>
     483           120719:     T *takeAs() {
     484           120719:       return static_cast<T*>(take());
     485                 :     }
     486                 : 
     487                 :     /// Alias for interface familiarity with unique_ptr.
     488           103741:     void *release() { return take(); }
     489                 : 
     490                 :     /// Pass ownership to a classical ActionResult.
     491                 :     DumbResult result() {
     492                 :       if (isInvalid())
     493                 :         return true;
     494                 :       return take();
     495                 :     }
     496                 : 
     497                 :     /// Move hook
     498          2257719:     operator moving::ASTResultMover<Destroyer>() {
     499          2257719:       return moving::ASTResultMover<Destroyer>(*this);
     500                 :     }
     501                 :   };
     502                 : #else
     503                 :   template <ASTDestroyer Destroyer>
     504                 :   class ASTOwningResult {
     505                 :   public:
     506                 :     typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
     507                 : 
     508                 :   private:
     509                 :     DumbResult Result;
     510                 : 
     511                 :   public:
     512                 :     explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
     513                 :       : Result(invalid) { }
     514                 :     ASTOwningResult(ActionBase &actions, void *node) : Result(node) { }
     515                 :     ASTOwningResult(ActionBase &actions, const DumbResult &res) : Result(res) { }
     516                 :     // Normal copying semantics are defined implicitly.
     517                 :     ASTOwningResult(const ASTOwningPtr<Destroyer> &o) : Result(o.get()) { }
     518                 : 
     519                 :     /// Assignment from a raw pointer. Takes ownership - beware!
     520                 :     ASTOwningResult & operator =(void *raw) {
     521                 :       Result = raw;
     522                 :       return *this;
     523                 :     }
     524                 : 
     525                 :     /// Assignment from an ActionResult. Takes ownership - beware!
     526                 :     ASTOwningResult & operator =(const DumbResult &res) {
     527                 :       Result = res;
     528                 :       return *this;
     529                 :     }
     530                 : 
     531                 :     /// Access to the raw pointer.
     532                 :     void * get() const { return Result.get(); }
     533                 : 
     534                 :     bool isInvalid() const { return Result.isInvalid(); }
     535                 : 
     536                 :     /// Does this point to a usable AST node? To be usable, the node must be
     537                 :     /// valid and non-null.
     538                 :     bool isUsable() const { return !Result.isInvalid() && get(); }
     539                 : 
     540                 :     /// Take outside ownership of the raw pointer.
     541                 :     void * take() {
     542                 :       return Result.get();
     543                 :     }
     544                 : 
     545                 :     /// Take outside ownership of the raw pointer and cast it down.
     546                 :     template<typename T>
     547                 :     T *takeAs() {
     548                 :       return static_cast<T*>(take());
     549                 :     }
     550                 : 
     551                 :     /// Alias for interface familiarity with unique_ptr.
     552                 :     void * release() { return take(); }
     553                 : 
     554                 :     /// Pass ownership to a classical ActionResult.
     555                 :     DumbResult result() { return Result; }
     556                 :   };
     557                 : #endif
     558                 : 
     559                 :   template <ASTDestroyer Destroyer>
     560                 :   class ASTMultiPtr {
     561                 : #if !defined(DISABLE_SMART_POINTERS)
     562                 :     ActionBase &Actions;
     563                 : #endif
     564                 :     void **Nodes;
     565                 :     unsigned Count;
     566                 : 
     567                 : #if !defined(DISABLE_SMART_POINTERS)
     568                 :     friend class moving::ASTMultiMover<Destroyer>;
     569                 : 
     570                 : #if defined(_MSC_VER)
     571                 :     //  Last tested with Visual Studio 2008.
     572                 :     //  Visual C++ appears to have a bug where it does not recognise
     573                 :     //  the return value from ASTMultiMover<Destroyer>::opeator-> as
     574                 :     //  being a pointer to ASTMultiPtr.  However, the diagnostics
     575                 :     //  suggest it has the right name, simply that the pointer type
     576                 :     //  is not convertible to itself.
     577                 :     //  Either way, a classic C-style hard cast resolves any issue.
     578                 :      static ASTMultiPtr* hack(moving::ASTMultiMover<Destroyer> & source) {
     579                 :        return (ASTMultiPtr*)source.operator->();
     580                 :      }
     581                 : #endif
     582                 : 
     583                 :     ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT
     584                 :     // Reference member prevents copy assignment.
     585                 : 
     586                 :     void destroy() {
     587                 :       assert((Count == 0 || Nodes) && "No nodes when count is not zero.");
     588                 :       for (unsigned i = 0; i < Count; ++i) {
     589                 :         if (Nodes[i])
     590                 :           (Actions.*Destroyer)(Nodes[i]);
     591                 :       }
     592                 :     }
     593                 : #endif
     594                 : 
     595                 :   public:
     596                 : #if !defined(DISABLE_SMART_POINTERS)
     597            26848:     explicit ASTMultiPtr(ActionBase &actions)
     598            26848:       : Actions(actions), Nodes(0), Count(0) {}
     599            61350:     ASTMultiPtr(ActionBase &actions, void **nodes, unsigned count)
     600            61350:       : Actions(actions), Nodes(nodes), Count(count) {}
     601                 :     /// Move constructor
     602           214005:     ASTMultiPtr(moving::ASTMultiMover<Destroyer> mover)
     603                 : #if defined(_MSC_VER)
     604                 :     //  Apply the visual C++ hack supplied above.
     605                 :     //  Last tested with Visual Studio 2008.
     606                 :       : Actions(hack(mover)->Actions), Nodes(hack(mover)->Nodes), Count(hack(mover)->Count) {
     607                 : #else
     608           214005:       : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) {
     609                 : #endif
     610           214005:       mover.release();
     611           214005:     }
     612                 : #else
     613                 :     // Normal copying implicitly defined
     614                 :     explicit ASTMultiPtr(ActionBase &) : Nodes(0), Count(0) {}
     615                 :     ASTMultiPtr(ActionBase &, void **nodes, unsigned count)
     616                 :       : Nodes(nodes), Count(count) {}
     617                 :     // Fake mover in Parse/AstGuard.h needs this:
     618                 :     ASTMultiPtr(void **nodes, unsigned count) : Nodes(nodes), Count(count) {}
     619                 : #endif
     620                 : 
     621                 : #if !defined(DISABLE_SMART_POINTERS)
     622                 :     /// Move assignment
     623                 :     ASTMultiPtr & operator =(moving::ASTMultiMover<Destroyer> mover) {
     624                 :       destroy();
     625                 :       Nodes = mover->Nodes;
     626                 :       Count = mover->Count;
     627                 :       mover.release();
     628                 :       return *this;
     629                 :     }
     630                 : #endif
     631                 : 
     632                 :     /// Access to the raw pointers.
     633            53227:     void ** get() const { return Nodes; }
     634                 : 
     635                 :     /// Access to the count.
     636            80241:     unsigned size() const { return Count; }
     637                 : 
     638            28223:     void ** release() {
     639                 : #if !defined(DISABLE_SMART_POINTERS)
     640            28223:       void **tmp = Nodes;
     641            28223:       Nodes = 0;
     642            28223:       Count = 0;
     643            28223:       return tmp;
     644                 : #else
     645                 :       return Nodes;
     646                 : #endif
     647                 :     }
     648                 : 
     649                 : #if !defined(DISABLE_SMART_POINTERS)
     650                 :     /// Move hook
     651           177521:     operator moving::ASTMultiMover<Destroyer>() {
     652           177521:       return moving::ASTMultiMover<Destroyer>(*this);
     653                 :     }
     654                 : #endif
     655                 :   };
     656                 : 
     657                 :   class ParsedTemplateArgument;
     658                 :     
     659                 :   class ASTTemplateArgsPtr {
     660                 : #if !defined(DISABLE_SMART_POINTERS)
     661                 :     ActionBase &Actions;
     662                 : #endif
     663                 :     ParsedTemplateArgument *Args;
     664                 :     mutable unsigned Count;
     665                 : 
     666                 : #if !defined(DISABLE_SMART_POINTERS)
     667                 :     void destroy();
     668                 : #endif
     669                 :     
     670                 :   public:
     671                 :     ASTTemplateArgsPtr(ActionBase &actions, ParsedTemplateArgument *args,
     672             5064:                        unsigned count) :
     673                 : #if !defined(DISABLE_SMART_POINTERS)
     674                 :       Actions(actions),
     675                 : #endif
     676             5064:       Args(args), Count(count) { }
     677                 : 
     678                 :     // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
     679             2301:     ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) :
     680                 : #if !defined(DISABLE_SMART_POINTERS)
     681                 :       Actions(Other.Actions),
     682                 : #endif
     683             2301:       Args(Other.Args), Count(Other.Count) {
     684                 : #if !defined(DISABLE_SMART_POINTERS)
     685             2301:       Other.Count = 0;
     686                 : #endif
     687             2301:     }
     688                 : 
     689                 :     // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
     690                 :     ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other)  {
     691                 : #if !defined(DISABLE_SMART_POINTERS)
     692                 :       Actions = Other.Actions;
     693                 : #endif
     694                 :       Args = Other.Args;
     695                 :       Count = Other.Count;
     696                 : #if !defined(DISABLE_SMART_POINTERS)
     697                 :       Other.Count = 0;
     698                 : #endif
     699                 :       return *this;
     700                 :     }
     701                 : 
     702                 : #if !defined(DISABLE_SMART_POINTERS)
     703             7365:     ~ASTTemplateArgsPtr() { destroy(); }
     704                 : #endif
     705                 : 
     706                 :     ParsedTemplateArgument *getArgs() const { return Args; }
     707             2527:     unsigned size() const { return Count; }
     708                 : 
     709                 :     void reset(ParsedTemplateArgument *args, unsigned count) {
     710                 : #if !defined(DISABLE_SMART_POINTERS)
     711                 :       destroy();
     712                 : #endif
     713                 :       Args = args;
     714                 :       Count = count;
     715                 :     }
     716                 : 
     717                 :     const ParsedTemplateArgument &operator[](unsigned Arg) const;
     718                 : 
     719             5044:     ParsedTemplateArgument *release() const {
     720                 : #if !defined(DISABLE_SMART_POINTERS)
     721             5044:       Count = 0;
     722                 : #endif
     723             5044:       return Args;
     724                 :     }
     725                 :   };
     726                 : 
     727                 :   /// \brief A small vector that owns a set of AST nodes.
     728                 :   template <ASTDestroyer Destroyer, unsigned N = 8>
     729                 :   class ASTOwningVector : public llvm::SmallVector<void *, N> {
     730                 : #if !defined(DISABLE_SMART_POINTERS)
     731                 :     ActionBase &Actions;
     732                 :     bool Owned;
     733                 : #endif
     734                 : 
     735                 :     ASTOwningVector(ASTOwningVector &); // do not implement
     736                 :     ASTOwningVector &operator=(ASTOwningVector &); // do not implement
     737                 : 
     738                 :   public:
     739            26333:     explicit ASTOwningVector(ActionBase &Actions)
     740                 : #if !defined(DISABLE_SMART_POINTERS)
     741            26333:       : Actions(Actions), Owned(true)
     742                 : #endif
     743            26333:     { }
     744                 : 
     745                 : #if !defined(DISABLE_SMART_POINTERS)
     746            26333:     ~ASTOwningVector() {
                      313: branch 2 taken
                      313: branch 3 taken
                      250: branch 3 taken
                       30: branch 4 taken
                        5: branch 5 taken
     747            26333:       if (!Owned)
     748            25572:         return;
     749                 : 
                       88: branch 1 taken
                      462: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                       17: branch 7 taken
                        5: branch 8 taken
     750              872:       for (unsigned I = 0, Last = this->size(); I != Last; ++I)
                      462: branch 3 taken
                    23254: branch 4 taken
                        5: branch 13 taken
                       30: branch 14 taken
     751            52777:         (Actions.*Destroyer)((*this)[I]);
     752            26333:     }
     753                 : #endif
     754                 : 
     755            25572:     void **take() {
     756                 : #if !defined(DISABLE_SMART_POINTERS)
     757            25572:       Owned = false;
     758                 : #endif
     759            25572:       return &this->front();
     760                 :     }
     761                 : 
     762                 :     template<typename T> T **takeAs() { return (T**)take(); }
     763                 : 
     764                 : #if !defined(DISABLE_SMART_POINTERS)
     765            22337:     ActionBase &getActions() const { return Actions; }
     766                 : #endif
     767                 :   };
     768                 : 
     769                 :   /// A SmallVector of statements, with stack size 32 (as that is the only one
     770                 :   /// used.)
     771                 :   typedef ASTOwningVector<&ActionBase::DeleteStmt, 32> StmtVector;
     772                 :   /// A SmallVector of expressions, with stack size 12 (the maximum used.)
     773                 :   typedef ASTOwningVector<&ActionBase::DeleteExpr, 12> ExprVector;
     774                 : 
     775                 :   template <ASTDestroyer Destroyer, unsigned N> inline
     776            22337:   ASTMultiPtr<Destroyer> move_arg(ASTOwningVector<Destroyer, N> &vec) {
     777                 : #if !defined(DISABLE_SMART_POINTERS)
     778            22337:     return ASTMultiPtr<Destroyer>(vec.getActions(), vec.take(), vec.size());
     779                 : #else
     780                 :     return ASTMultiPtr<Destroyer>(vec.take(), vec.size());
     781                 : #endif
     782                 :   }
     783                 : 
     784                 : #if !defined(DISABLE_SMART_POINTERS)
     785                 : 
     786                 :   // Out-of-line implementations due to definition dependencies
     787                 : 
     788                 :   template <ASTDestroyer Destroyer> inline
     789           214005:   void moving::ASTMultiMover<Destroyer>::release() {
     790           214005:     Moved.Nodes = 0;
     791           214005:     Moved.Count = 0;
     792           214005:   }
     793                 : 
     794                 :   // Move overloads.
     795                 : 
     796                 :   template <ASTDestroyer Destroyer> inline
     797           513870:   ASTOwningResult<Destroyer> move(ASTOwningResult<Destroyer> &ptr) {
     798           513870:     return ASTOwningResult<Destroyer>(moving::ASTResultMover<Destroyer>(ptr));
     799                 :   }
     800                 : 
     801                 :   template <ASTDestroyer Destroyer> inline
     802            36484:   ASTMultiPtr<Destroyer> move(ASTMultiPtr<Destroyer> &ptr) {
     803            36484:     return ASTMultiPtr<Destroyer>(moving::ASTMultiMover<Destroyer>(ptr));
     804                 :   }
     805                 : 
     806                 : #else
     807                 : 
     808                 :   template <ASTDestroyer Destroyer> inline
     809                 :   ASTOwningPtr<Destroyer>::ASTOwningPtr(const ASTOwningResult<Destroyer> &o)
     810                 :     : Node(o.get()) { }
     811                 : 
     812                 :   // These versions are hopefully no-ops.
     813                 :   template <ASTDestroyer Destroyer> inline
     814                 :   ASTOwningResult<Destroyer>& move(ASTOwningResult<Destroyer> &ptr) {
     815                 :     return ptr;
     816                 :   }
     817                 : 
     818                 :   template <ASTDestroyer Destroyer> inline
     819                 :   ASTOwningPtr<Destroyer>& move(ASTOwningPtr<Destroyer> &ptr) {
     820                 :     return ptr;
     821                 :   }
     822                 : 
     823                 :   template <ASTDestroyer Destroyer> inline
     824                 :   ASTMultiPtr<Destroyer>& move(ASTMultiPtr<Destroyer> &ptr) {
     825                 :     return ptr;
     826                 :   }
     827                 : #endif
     828                 : }
     829                 : 
     830                 : #endif

Generated: 2010-02-10 01:31 by zcov