Home | History | Annotate | Download | only in Sema
      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_SEMA_OWNERSHIP_H
     15 #define LLVM_CLANG_SEMA_OWNERSHIP_H
     16 
     17 #include "clang/Basic/LLVM.h"
     18 #include "llvm/ADT/ArrayRef.h"
     19 #include "llvm/ADT/PointerIntPair.h"
     20 
     21 //===----------------------------------------------------------------------===//
     22 // OpaquePtr
     23 //===----------------------------------------------------------------------===//
     24 
     25 namespace clang {
     26   class CXXCtorInitializer;
     27   class CXXBaseSpecifier;
     28   class Decl;
     29   class Expr;
     30   class ParsedTemplateArgument;
     31   class QualType;
     32   class Stmt;
     33   class TemplateName;
     34   class TemplateParameterList;
     35 
     36   /// OpaquePtr - This is a very simple POD type that wraps a pointer that the
     37   /// Parser doesn't know about but that Sema or another client does.  The UID
     38   /// template argument is used to make sure that "Decl" pointers are not
     39   /// compatible with "Type" pointers for example.
     40   template <class PtrTy>
     41   class OpaquePtr {
     42     void *Ptr;
     43     explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {}
     44 
     45     typedef llvm::PointerLikeTypeTraits<PtrTy> Traits;
     46 
     47   public:
     48     OpaquePtr() : Ptr(0) {}
     49 
     50     static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
     51 
     52     template <typename T> T* getAs() const {
     53       return get();
     54     }
     55 
     56     template <typename T> T getAsVal() const {
     57       return get();
     58     }
     59 
     60     PtrTy get() const {
     61       return Traits::getFromVoidPointer(Ptr);
     62     }
     63 
     64     void set(PtrTy P) {
     65       Ptr = Traits::getAsVoidPointer(P);
     66     }
     67 
     68     operator bool() const { return Ptr != 0; }
     69 
     70     void *getAsOpaquePtr() const { return Ptr; }
     71     static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
     72   };
     73 
     74   /// UnionOpaquePtr - A version of OpaquePtr suitable for membership
     75   /// in a union.
     76   template <class T> struct UnionOpaquePtr {
     77     void *Ptr;
     78 
     79     static UnionOpaquePtr make(OpaquePtr<T> P) {
     80       UnionOpaquePtr OP = { P.getAsOpaquePtr() };
     81       return OP;
     82     }
     83 
     84     OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); }
     85     operator OpaquePtr<T>() const { return get(); }
     86 
     87     UnionOpaquePtr &operator=(OpaquePtr<T> P) {
     88       Ptr = P.getAsOpaquePtr();
     89       return *this;
     90     }
     91   };
     92 }
     93 
     94 namespace llvm {
     95   template <class T>
     96   class PointerLikeTypeTraits<clang::OpaquePtr<T> > {
     97   public:
     98     static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) {
     99       // FIXME: Doesn't work? return P.getAs< void >();
    100       return P.getAsOpaquePtr();
    101     }
    102     static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) {
    103       return clang::OpaquePtr<T>::getFromOpaquePtr(P);
    104     }
    105     enum { NumLowBitsAvailable = 0 };
    106   };
    107 
    108   template <class T>
    109   struct isPodLike<clang::OpaquePtr<T> > { static const bool value = true; };
    110 }
    111 
    112 namespace clang {
    113   // Basic
    114   class DiagnosticBuilder;
    115 
    116   // Determines whether the low bit of the result pointer for the
    117   // given UID is always zero. If so, ActionResult will use that bit
    118   // for it's "invalid" flag.
    119   template<class Ptr>
    120   struct IsResultPtrLowBitFree {
    121     static const bool value = false;
    122   };
    123 
    124   /// ActionResult - This structure is used while parsing/acting on
    125   /// expressions, stmts, etc.  It encapsulates both the object returned by
    126   /// the action, plus a sense of whether or not it is valid.
    127   /// When CompressInvalid is true, the "invalid" flag will be
    128   /// stored in the low bit of the Val pointer.
    129   template<class PtrTy,
    130            bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value>
    131   class ActionResult {
    132     PtrTy Val;
    133     bool Invalid;
    134 
    135   public:
    136     ActionResult(bool Invalid = false)
    137       : Val(PtrTy()), Invalid(Invalid) {}
    138     ActionResult(PtrTy val) : Val(val), Invalid(false) {}
    139     ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
    140 
    141     // These two overloads prevent void* -> bool conversions.
    142     ActionResult(const void *);
    143     ActionResult(volatile void *);
    144 
    145     bool isInvalid() const { return Invalid; }
    146     bool isUsable() const { return !Invalid && Val; }
    147 
    148     PtrTy get() const { return Val; }
    149     // FIXME: Replace with get.
    150     PtrTy release() const { return Val; }
    151     PtrTy take() const { return Val; }
    152     template <typename T> T *takeAs() { return static_cast<T*>(get()); }
    153 
    154     void set(PtrTy V) { Val = V; }
    155 
    156     const ActionResult &operator=(PtrTy RHS) {
    157       Val = RHS;
    158       Invalid = false;
    159       return *this;
    160     }
    161   };
    162 
    163   // This ActionResult partial specialization places the "invalid"
    164   // flag into the low bit of the pointer.
    165   template<typename PtrTy>
    166   class ActionResult<PtrTy, true> {
    167     // A pointer whose low bit is 1 if this result is invalid, 0
    168     // otherwise.
    169     uintptr_t PtrWithInvalid;
    170     typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
    171   public:
    172     ActionResult(bool Invalid = false)
    173       : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
    174 
    175     ActionResult(PtrTy V) {
    176       void *VP = PtrTraits::getAsVoidPointer(V);
    177       PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
    178       assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
    179     }
    180     ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
    181 
    182     // These two overloads prevent void* -> bool conversions.
    183     ActionResult(const void *);
    184     ActionResult(volatile void *);
    185 
    186     bool isInvalid() const { return PtrWithInvalid & 0x01; }
    187     bool isUsable() const { return PtrWithInvalid > 0x01; }
    188 
    189     PtrTy get() const {
    190       void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
    191       return PtrTraits::getFromVoidPointer(VP);
    192     }
    193     // FIXME: Replace with get.
    194     PtrTy take() const { return get(); }
    195     PtrTy release() const { return get(); }
    196     template <typename T> T *takeAs() { return static_cast<T*>(get()); }
    197 
    198     void set(PtrTy V) {
    199       void *VP = PtrTraits::getAsVoidPointer(V);
    200       PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
    201       assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
    202     }
    203 
    204     const ActionResult &operator=(PtrTy RHS) {
    205       void *VP = PtrTraits::getAsVoidPointer(RHS);
    206       PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
    207       assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
    208       return *this;
    209     }
    210   };
    211 
    212   /// An opaque type for threading parsed type information through the
    213   /// parser.
    214   typedef OpaquePtr<QualType> ParsedType;
    215   typedef UnionOpaquePtr<QualType> UnionParsedType;
    216 
    217   // We can re-use the low bit of expression, statement, base, and
    218   // member-initializer pointers for the "invalid" flag of
    219   // ActionResult.
    220   template<> struct IsResultPtrLowBitFree<Expr*> {
    221     static const bool value = true;
    222   };
    223   template<> struct IsResultPtrLowBitFree<Stmt*> {
    224     static const bool value = true;
    225   };
    226   template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> {
    227     static const bool value = true;
    228   };
    229   template<> struct IsResultPtrLowBitFree<CXXCtorInitializer*> {
    230     static const bool value = true;
    231   };
    232 
    233   typedef ActionResult<Expr*> ExprResult;
    234   typedef ActionResult<Stmt*> StmtResult;
    235   typedef ActionResult<ParsedType> TypeResult;
    236   typedef ActionResult<CXXBaseSpecifier*> BaseResult;
    237   typedef ActionResult<CXXCtorInitializer*> MemInitResult;
    238 
    239   typedef ActionResult<Decl*> DeclResult;
    240   typedef OpaquePtr<TemplateName> ParsedTemplateTy;
    241 
    242   typedef llvm::MutableArrayRef<Expr*> MultiExprArg;
    243   typedef llvm::MutableArrayRef<Stmt*> MultiStmtArg;
    244   typedef llvm::MutableArrayRef<ParsedTemplateArgument> ASTTemplateArgsPtr;
    245   typedef llvm::MutableArrayRef<ParsedType> MultiTypeArg;
    246   typedef llvm::MutableArrayRef<TemplateParameterList*> MultiTemplateParamsArg;
    247 
    248   inline ExprResult ExprError() { return ExprResult(true); }
    249   inline StmtResult StmtError() { return StmtResult(true); }
    250 
    251   inline ExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
    252   inline StmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
    253 
    254   inline ExprResult ExprEmpty() { return ExprResult(false); }
    255   inline StmtResult StmtEmpty() { return StmtResult(false); }
    256 
    257   inline Expr *AssertSuccess(ExprResult R) {
    258     assert(!R.isInvalid() && "operation was asserted to never fail!");
    259     return R.get();
    260   }
    261 
    262   inline Stmt *AssertSuccess(StmtResult R) {
    263     assert(!R.isInvalid() && "operation was asserted to never fail!");
    264     return R.get();
    265   }
    266 }
    267 
    268 #endif
    269