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