Ownership.h revision 251662
1212795Sdim//===--- Ownership.h - Parser ownership helpers -----------------*- C++ -*-===// 2212795Sdim// 3212795Sdim// The LLVM Compiler Infrastructure 4212795Sdim// 5212795Sdim// This file is distributed under the University of Illinois Open Source 6212795Sdim// License. See LICENSE.TXT for details. 7212795Sdim// 8212795Sdim//===----------------------------------------------------------------------===// 9212795Sdim// 10212795Sdim// This file contains classes for managing ownership of Stmt and Expr nodes. 11212795Sdim// 12212795Sdim//===----------------------------------------------------------------------===// 13212795Sdim 14212795Sdim#ifndef LLVM_CLANG_SEMA_OWNERSHIP_H 15212795Sdim#define LLVM_CLANG_SEMA_OWNERSHIP_H 16212795Sdim 17226633Sdim#include "clang/Basic/LLVM.h" 18243830Sdim#include "llvm/ADT/ArrayRef.h" 19212795Sdim#include "llvm/ADT/PointerIntPair.h" 20212795Sdim 21212795Sdim//===----------------------------------------------------------------------===// 22212795Sdim// OpaquePtr 23212795Sdim//===----------------------------------------------------------------------===// 24212795Sdim 25212795Sdimnamespace clang { 26218893Sdim class CXXCtorInitializer; 27212795Sdim class CXXBaseSpecifier; 28212795Sdim class Decl; 29212795Sdim class Expr; 30243830Sdim class ParsedTemplateArgument; 31212795Sdim class QualType; 32212795Sdim class Stmt; 33212795Sdim class TemplateName; 34212795Sdim class TemplateParameterList; 35212795Sdim 36212795Sdim /// OpaquePtr - This is a very simple POD type that wraps a pointer that the 37212795Sdim /// Parser doesn't know about but that Sema or another client does. The UID 38212795Sdim /// template argument is used to make sure that "Decl" pointers are not 39212795Sdim /// compatible with "Type" pointers for example. 40212795Sdim template <class PtrTy> 41212795Sdim class OpaquePtr { 42212795Sdim void *Ptr; 43212795Sdim explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {} 44212795Sdim 45212795Sdim typedef llvm::PointerLikeTypeTraits<PtrTy> Traits; 46212795Sdim 47212795Sdim public: 48212795Sdim OpaquePtr() : Ptr(0) {} 49212795Sdim 50212795Sdim static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; } 51212795Sdim 52212795Sdim template <typename T> T* getAs() const { 53212795Sdim return get(); 54212795Sdim } 55212795Sdim 56212795Sdim template <typename T> T getAsVal() const { 57212795Sdim return get(); 58212795Sdim } 59212795Sdim 60212795Sdim PtrTy get() const { 61212795Sdim return Traits::getFromVoidPointer(Ptr); 62212795Sdim } 63212795Sdim 64212795Sdim void set(PtrTy P) { 65212795Sdim Ptr = Traits::getAsVoidPointer(P); 66212795Sdim } 67212795Sdim 68212795Sdim operator bool() const { return Ptr != 0; } 69212795Sdim 70212795Sdim void *getAsOpaquePtr() const { return Ptr; } 71212795Sdim static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); } 72212795Sdim }; 73212795Sdim 74212795Sdim /// UnionOpaquePtr - A version of OpaquePtr suitable for membership 75212795Sdim /// in a union. 76212795Sdim template <class T> struct UnionOpaquePtr { 77212795Sdim void *Ptr; 78212795Sdim 79212795Sdim static UnionOpaquePtr make(OpaquePtr<T> P) { 80212795Sdim UnionOpaquePtr OP = { P.getAsOpaquePtr() }; 81212795Sdim return OP; 82212795Sdim } 83212795Sdim 84212795Sdim OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); } 85212795Sdim operator OpaquePtr<T>() const { return get(); } 86212795Sdim 87212795Sdim UnionOpaquePtr &operator=(OpaquePtr<T> P) { 88212795Sdim Ptr = P.getAsOpaquePtr(); 89212795Sdim return *this; 90212795Sdim } 91212795Sdim }; 92212795Sdim} 93212795Sdim 94212795Sdimnamespace llvm { 95212795Sdim template <class T> 96212795Sdim class PointerLikeTypeTraits<clang::OpaquePtr<T> > { 97212795Sdim public: 98212795Sdim static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) { 99212795Sdim // FIXME: Doesn't work? return P.getAs< void >(); 100212795Sdim return P.getAsOpaquePtr(); 101212795Sdim } 102212795Sdim static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) { 103212795Sdim return clang::OpaquePtr<T>::getFromOpaquePtr(P); 104212795Sdim } 105212795Sdim enum { NumLowBitsAvailable = 0 }; 106212795Sdim }; 107218893Sdim 108218893Sdim template <class T> 109218893Sdim struct isPodLike<clang::OpaquePtr<T> > { static const bool value = true; }; 110212795Sdim} 111212795Sdim 112212795Sdimnamespace clang { 113212795Sdim // Basic 114212795Sdim class DiagnosticBuilder; 115212795Sdim 116212795Sdim // Determines whether the low bit of the result pointer for the 117212795Sdim // given UID is always zero. If so, ActionResult will use that bit 118212795Sdim // for it's "invalid" flag. 119212795Sdim template<class Ptr> 120212795Sdim struct IsResultPtrLowBitFree { 121212795Sdim static const bool value = false; 122212795Sdim }; 123212795Sdim 124212795Sdim /// ActionResult - This structure is used while parsing/acting on 125212795Sdim /// expressions, stmts, etc. It encapsulates both the object returned by 126212795Sdim /// the action, plus a sense of whether or not it is valid. 127212795Sdim /// When CompressInvalid is true, the "invalid" flag will be 128212795Sdim /// stored in the low bit of the Val pointer. 129212795Sdim template<class PtrTy, 130212795Sdim bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value> 131212795Sdim class ActionResult { 132212795Sdim PtrTy Val; 133212795Sdim bool Invalid; 134212795Sdim 135212795Sdim public: 136212795Sdim ActionResult(bool Invalid = false) 137212795Sdim : Val(PtrTy()), Invalid(Invalid) {} 138212795Sdim ActionResult(PtrTy val) : Val(val), Invalid(false) {} 139212795Sdim ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {} 140212795Sdim 141212795Sdim // These two overloads prevent void* -> bool conversions. 142212795Sdim ActionResult(const void *); 143212795Sdim ActionResult(volatile void *); 144212795Sdim 145212795Sdim bool isInvalid() const { return Invalid; } 146212795Sdim bool isUsable() const { return !Invalid && Val; } 147212795Sdim 148212795Sdim PtrTy get() const { return Val; } 149243830Sdim // FIXME: Replace with get. 150212795Sdim PtrTy release() const { return Val; } 151212795Sdim PtrTy take() const { return Val; } 152212795Sdim template <typename T> T *takeAs() { return static_cast<T*>(get()); } 153212795Sdim 154212795Sdim void set(PtrTy V) { Val = V; } 155212795Sdim 156212795Sdim const ActionResult &operator=(PtrTy RHS) { 157212795Sdim Val = RHS; 158212795Sdim Invalid = false; 159212795Sdim return *this; 160212795Sdim } 161212795Sdim }; 162212795Sdim 163212795Sdim // This ActionResult partial specialization places the "invalid" 164212795Sdim // flag into the low bit of the pointer. 165212795Sdim template<typename PtrTy> 166212795Sdim class ActionResult<PtrTy, true> { 167212795Sdim // A pointer whose low bit is 1 if this result is invalid, 0 168212795Sdim // otherwise. 169212795Sdim uintptr_t PtrWithInvalid; 170212795Sdim typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits; 171212795Sdim public: 172212795Sdim ActionResult(bool Invalid = false) 173212795Sdim : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { } 174212795Sdim 175212795Sdim ActionResult(PtrTy V) { 176212795Sdim void *VP = PtrTraits::getAsVoidPointer(V); 177212795Sdim PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); 178212795Sdim assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); 179212795Sdim } 180212795Sdim ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { } 181212795Sdim 182212795Sdim // These two overloads prevent void* -> bool conversions. 183212795Sdim ActionResult(const void *); 184212795Sdim ActionResult(volatile void *); 185212795Sdim 186212795Sdim bool isInvalid() const { return PtrWithInvalid & 0x01; } 187212795Sdim bool isUsable() const { return PtrWithInvalid > 0x01; } 188212795Sdim 189212795Sdim PtrTy get() const { 190212795Sdim void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01); 191212795Sdim return PtrTraits::getFromVoidPointer(VP); 192212795Sdim } 193243830Sdim // FIXME: Replace with get. 194212795Sdim PtrTy take() const { return get(); } 195212795Sdim PtrTy release() const { return get(); } 196212795Sdim template <typename T> T *takeAs() { return static_cast<T*>(get()); } 197212795Sdim 198212795Sdim void set(PtrTy V) { 199212795Sdim void *VP = PtrTraits::getAsVoidPointer(V); 200212795Sdim PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); 201212795Sdim assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); 202212795Sdim } 203212795Sdim 204212795Sdim const ActionResult &operator=(PtrTy RHS) { 205212795Sdim void *VP = PtrTraits::getAsVoidPointer(RHS); 206212795Sdim PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); 207212795Sdim assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); 208212795Sdim return *this; 209212795Sdim } 210251662Sdim 211251662Sdim // For types where we can fit a flag in with the pointer, provide 212251662Sdim // conversions to/from pointer type. 213251662Sdim static ActionResult getFromOpaquePointer(void *P) { 214251662Sdim ActionResult Result; 215251662Sdim Result.PtrWithInvalid = (uintptr_t)P; 216251662Sdim return Result; 217251662Sdim } 218251662Sdim void *getAsOpaquePointer() const { return (void*)PtrWithInvalid; } 219212795Sdim }; 220212795Sdim 221221345Sdim /// An opaque type for threading parsed type information through the 222221345Sdim /// parser. 223221345Sdim typedef OpaquePtr<QualType> ParsedType; 224221345Sdim typedef UnionOpaquePtr<QualType> UnionParsedType; 225221345Sdim 226212795Sdim // We can re-use the low bit of expression, statement, base, and 227212795Sdim // member-initializer pointers for the "invalid" flag of 228212795Sdim // ActionResult. 229212795Sdim template<> struct IsResultPtrLowBitFree<Expr*> { 230212795Sdim static const bool value = true; 231212795Sdim }; 232212795Sdim template<> struct IsResultPtrLowBitFree<Stmt*> { 233212795Sdim static const bool value = true; 234212795Sdim }; 235212795Sdim template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> { 236212795Sdim static const bool value = true; 237212795Sdim }; 238218893Sdim template<> struct IsResultPtrLowBitFree<CXXCtorInitializer*> { 239212795Sdim static const bool value = true; 240212795Sdim }; 241212795Sdim 242212795Sdim typedef ActionResult<Expr*> ExprResult; 243212795Sdim typedef ActionResult<Stmt*> StmtResult; 244212795Sdim typedef ActionResult<ParsedType> TypeResult; 245212795Sdim typedef ActionResult<CXXBaseSpecifier*> BaseResult; 246218893Sdim typedef ActionResult<CXXCtorInitializer*> MemInitResult; 247212795Sdim 248212795Sdim typedef ActionResult<Decl*> DeclResult; 249212795Sdim typedef OpaquePtr<TemplateName> ParsedTemplateTy; 250212795Sdim 251243830Sdim typedef llvm::MutableArrayRef<Expr*> MultiExprArg; 252243830Sdim typedef llvm::MutableArrayRef<Stmt*> MultiStmtArg; 253243830Sdim typedef llvm::MutableArrayRef<ParsedTemplateArgument> ASTTemplateArgsPtr; 254243830Sdim typedef llvm::MutableArrayRef<ParsedType> MultiTypeArg; 255243830Sdim typedef llvm::MutableArrayRef<TemplateParameterList*> MultiTemplateParamsArg; 256212795Sdim 257212795Sdim inline ExprResult ExprError() { return ExprResult(true); } 258212795Sdim inline StmtResult StmtError() { return StmtResult(true); } 259212795Sdim 260212795Sdim inline ExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); } 261212795Sdim inline StmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); } 262212795Sdim 263212795Sdim inline ExprResult ExprEmpty() { return ExprResult(false); } 264212795Sdim inline StmtResult StmtEmpty() { return StmtResult(false); } 265212795Sdim 266212795Sdim inline Expr *AssertSuccess(ExprResult R) { 267212795Sdim assert(!R.isInvalid() && "operation was asserted to never fail!"); 268212795Sdim return R.get(); 269212795Sdim } 270212795Sdim 271212795Sdim inline Stmt *AssertSuccess(StmtResult R) { 272212795Sdim assert(!R.isInvalid() && "operation was asserted to never fail!"); 273212795Sdim return R.get(); 274212795Sdim } 275212795Sdim} 276212795Sdim 277212795Sdim#endif 278