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
36263508Sdim  /// \brief Wrapper for void* pointer.
37263508Sdim  /// \tparam PtrTy Either a pointer type like 'T*' or a type that behaves like
38263508Sdim  ///               a pointer.
39263508Sdim  ///
40263508Sdim  /// This is a very simple POD type that wraps a pointer that the Parser
41263508Sdim  /// doesn't know about but that Sema or another client does.  The PtrTy
42212795Sdim  /// template argument is used to make sure that "Decl" pointers are not
43212795Sdim  /// compatible with "Type" pointers for example.
44212795Sdim  template <class PtrTy>
45212795Sdim  class OpaquePtr {
46212795Sdim    void *Ptr;
47212795Sdim    explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {}
48212795Sdim
49212795Sdim    typedef llvm::PointerLikeTypeTraits<PtrTy> Traits;
50212795Sdim
51212795Sdim  public:
52212795Sdim    OpaquePtr() : Ptr(0) {}
53212795Sdim
54212795Sdim    static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
55212795Sdim
56263508Sdim    /// \brief Returns plain pointer to the entity pointed by this wrapper.
57263508Sdim    /// \tparam PointeeT Type of pointed entity.
58263508Sdim    ///
59263508Sdim    /// It is identical to getPtrAs<PointeeT*>.
60263508Sdim    template <typename PointeeT> PointeeT* getPtrTo() const {
61212795Sdim      return get();
62212795Sdim    }
63212795Sdim
64263508Sdim    /// \brief Returns pointer converted to the specified type.
65263508Sdim    /// \tparam PtrT Result pointer type.  There must be implicit conversion
66263508Sdim    ///              from PtrTy to PtrT.
67263508Sdim    ///
68263508Sdim    /// In contrast to getPtrTo, this method allows the return type to be
69263508Sdim    /// a smart pointer.
70263508Sdim    template <typename PtrT> PtrT getPtrAs() const {
71212795Sdim      return get();
72212795Sdim    }
73212795Sdim
74212795Sdim    PtrTy get() const {
75212795Sdim      return Traits::getFromVoidPointer(Ptr);
76212795Sdim    }
77212795Sdim
78212795Sdim    void set(PtrTy P) {
79212795Sdim      Ptr = Traits::getAsVoidPointer(P);
80212795Sdim    }
81212795Sdim
82263508Sdim    LLVM_EXPLICIT operator bool() const { return Ptr != 0; }
83212795Sdim
84212795Sdim    void *getAsOpaquePtr() const { return Ptr; }
85212795Sdim    static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
86212795Sdim  };
87212795Sdim
88212795Sdim  /// UnionOpaquePtr - A version of OpaquePtr suitable for membership
89212795Sdim  /// in a union.
90212795Sdim  template <class T> struct UnionOpaquePtr {
91212795Sdim    void *Ptr;
92212795Sdim
93212795Sdim    static UnionOpaquePtr make(OpaquePtr<T> P) {
94212795Sdim      UnionOpaquePtr OP = { P.getAsOpaquePtr() };
95212795Sdim      return OP;
96212795Sdim    }
97212795Sdim
98212795Sdim    OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); }
99212795Sdim    operator OpaquePtr<T>() const { return get(); }
100212795Sdim
101212795Sdim    UnionOpaquePtr &operator=(OpaquePtr<T> P) {
102212795Sdim      Ptr = P.getAsOpaquePtr();
103212795Sdim      return *this;
104212795Sdim    }
105212795Sdim  };
106212795Sdim}
107212795Sdim
108212795Sdimnamespace llvm {
109212795Sdim  template <class T>
110212795Sdim  class PointerLikeTypeTraits<clang::OpaquePtr<T> > {
111212795Sdim  public:
112212795Sdim    static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) {
113212795Sdim      // FIXME: Doesn't work? return P.getAs< void >();
114212795Sdim      return P.getAsOpaquePtr();
115212795Sdim    }
116212795Sdim    static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) {
117212795Sdim      return clang::OpaquePtr<T>::getFromOpaquePtr(P);
118212795Sdim    }
119212795Sdim    enum { NumLowBitsAvailable = 0 };
120212795Sdim  };
121218893Sdim
122218893Sdim  template <class T>
123218893Sdim  struct isPodLike<clang::OpaquePtr<T> > { static const bool value = true; };
124212795Sdim}
125212795Sdim
126212795Sdimnamespace clang {
127212795Sdim  // Basic
128212795Sdim  class DiagnosticBuilder;
129212795Sdim
130212795Sdim  // Determines whether the low bit of the result pointer for the
131212795Sdim  // given UID is always zero. If so, ActionResult will use that bit
132212795Sdim  // for it's "invalid" flag.
133212795Sdim  template<class Ptr>
134212795Sdim  struct IsResultPtrLowBitFree {
135212795Sdim    static const bool value = false;
136212795Sdim  };
137212795Sdim
138212795Sdim  /// ActionResult - This structure is used while parsing/acting on
139212795Sdim  /// expressions, stmts, etc.  It encapsulates both the object returned by
140212795Sdim  /// the action, plus a sense of whether or not it is valid.
141212795Sdim  /// When CompressInvalid is true, the "invalid" flag will be
142212795Sdim  /// stored in the low bit of the Val pointer.
143212795Sdim  template<class PtrTy,
144212795Sdim           bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value>
145212795Sdim  class ActionResult {
146212795Sdim    PtrTy Val;
147212795Sdim    bool Invalid;
148212795Sdim
149212795Sdim  public:
150212795Sdim    ActionResult(bool Invalid = false)
151212795Sdim      : Val(PtrTy()), Invalid(Invalid) {}
152212795Sdim    ActionResult(PtrTy val) : Val(val), Invalid(false) {}
153212795Sdim    ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
154212795Sdim
155212795Sdim    // These two overloads prevent void* -> bool conversions.
156212795Sdim    ActionResult(const void *);
157212795Sdim    ActionResult(volatile void *);
158212795Sdim
159212795Sdim    bool isInvalid() const { return Invalid; }
160212795Sdim    bool isUsable() const { return !Invalid && Val; }
161212795Sdim
162212795Sdim    PtrTy get() const { return Val; }
163243830Sdim    // FIXME: Replace with get.
164212795Sdim    PtrTy release() const { return Val; }
165212795Sdim    PtrTy take() const { return Val; }
166212795Sdim    template <typename T> T *takeAs() { return static_cast<T*>(get()); }
167212795Sdim
168212795Sdim    void set(PtrTy V) { Val = V; }
169212795Sdim
170212795Sdim    const ActionResult &operator=(PtrTy RHS) {
171212795Sdim      Val = RHS;
172212795Sdim      Invalid = false;
173212795Sdim      return *this;
174212795Sdim    }
175212795Sdim  };
176212795Sdim
177212795Sdim  // This ActionResult partial specialization places the "invalid"
178212795Sdim  // flag into the low bit of the pointer.
179212795Sdim  template<typename PtrTy>
180212795Sdim  class ActionResult<PtrTy, true> {
181212795Sdim    // A pointer whose low bit is 1 if this result is invalid, 0
182212795Sdim    // otherwise.
183212795Sdim    uintptr_t PtrWithInvalid;
184212795Sdim    typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
185212795Sdim  public:
186212795Sdim    ActionResult(bool Invalid = false)
187212795Sdim      : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
188212795Sdim
189212795Sdim    ActionResult(PtrTy V) {
190212795Sdim      void *VP = PtrTraits::getAsVoidPointer(V);
191212795Sdim      PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
192212795Sdim      assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
193212795Sdim    }
194212795Sdim    ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
195212795Sdim
196212795Sdim    // These two overloads prevent void* -> bool conversions.
197212795Sdim    ActionResult(const void *);
198212795Sdim    ActionResult(volatile void *);
199212795Sdim
200212795Sdim    bool isInvalid() const { return PtrWithInvalid & 0x01; }
201212795Sdim    bool isUsable() const { return PtrWithInvalid > 0x01; }
202212795Sdim
203212795Sdim    PtrTy get() const {
204212795Sdim      void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
205212795Sdim      return PtrTraits::getFromVoidPointer(VP);
206212795Sdim    }
207243830Sdim    // FIXME: Replace with get.
208212795Sdim    PtrTy take() const { return get(); }
209212795Sdim    PtrTy release() const { return get(); }
210212795Sdim    template <typename T> T *takeAs() { return static_cast<T*>(get()); }
211212795Sdim
212212795Sdim    void set(PtrTy V) {
213212795Sdim      void *VP = PtrTraits::getAsVoidPointer(V);
214212795Sdim      PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
215212795Sdim      assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
216212795Sdim    }
217212795Sdim
218212795Sdim    const ActionResult &operator=(PtrTy RHS) {
219212795Sdim      void *VP = PtrTraits::getAsVoidPointer(RHS);
220212795Sdim      PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
221212795Sdim      assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
222212795Sdim      return *this;
223212795Sdim    }
224251662Sdim
225251662Sdim    // For types where we can fit a flag in with the pointer, provide
226251662Sdim    // conversions to/from pointer type.
227251662Sdim    static ActionResult getFromOpaquePointer(void *P) {
228251662Sdim      ActionResult Result;
229251662Sdim      Result.PtrWithInvalid = (uintptr_t)P;
230251662Sdim      return Result;
231251662Sdim    }
232251662Sdim    void *getAsOpaquePointer() const { return (void*)PtrWithInvalid; }
233212795Sdim  };
234212795Sdim
235221345Sdim  /// An opaque type for threading parsed type information through the
236221345Sdim  /// parser.
237221345Sdim  typedef OpaquePtr<QualType> ParsedType;
238221345Sdim  typedef UnionOpaquePtr<QualType> UnionParsedType;
239221345Sdim
240212795Sdim  // We can re-use the low bit of expression, statement, base, and
241212795Sdim  // member-initializer pointers for the "invalid" flag of
242212795Sdim  // ActionResult.
243212795Sdim  template<> struct IsResultPtrLowBitFree<Expr*> {
244212795Sdim    static const bool value = true;
245212795Sdim  };
246212795Sdim  template<> struct IsResultPtrLowBitFree<Stmt*> {
247212795Sdim    static const bool value = true;
248212795Sdim  };
249212795Sdim  template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> {
250212795Sdim    static const bool value = true;
251212795Sdim  };
252218893Sdim  template<> struct IsResultPtrLowBitFree<CXXCtorInitializer*> {
253212795Sdim    static const bool value = true;
254212795Sdim  };
255212795Sdim
256212795Sdim  typedef ActionResult<Expr*> ExprResult;
257212795Sdim  typedef ActionResult<Stmt*> StmtResult;
258212795Sdim  typedef ActionResult<ParsedType> TypeResult;
259212795Sdim  typedef ActionResult<CXXBaseSpecifier*> BaseResult;
260218893Sdim  typedef ActionResult<CXXCtorInitializer*> MemInitResult;
261212795Sdim
262212795Sdim  typedef ActionResult<Decl*> DeclResult;
263212795Sdim  typedef OpaquePtr<TemplateName> ParsedTemplateTy;
264212795Sdim
265243830Sdim  typedef llvm::MutableArrayRef<Expr*> MultiExprArg;
266243830Sdim  typedef llvm::MutableArrayRef<Stmt*> MultiStmtArg;
267243830Sdim  typedef llvm::MutableArrayRef<ParsedTemplateArgument> ASTTemplateArgsPtr;
268243830Sdim  typedef llvm::MutableArrayRef<ParsedType> MultiTypeArg;
269243830Sdim  typedef llvm::MutableArrayRef<TemplateParameterList*> MultiTemplateParamsArg;
270212795Sdim
271212795Sdim  inline ExprResult ExprError() { return ExprResult(true); }
272212795Sdim  inline StmtResult StmtError() { return StmtResult(true); }
273212795Sdim
274212795Sdim  inline ExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
275212795Sdim  inline StmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
276212795Sdim
277212795Sdim  inline ExprResult ExprEmpty() { return ExprResult(false); }
278212795Sdim  inline StmtResult StmtEmpty() { return StmtResult(false); }
279212795Sdim
280212795Sdim  inline Expr *AssertSuccess(ExprResult R) {
281212795Sdim    assert(!R.isInvalid() && "operation was asserted to never fail!");
282212795Sdim    return R.get();
283212795Sdim  }
284212795Sdim
285212795Sdim  inline Stmt *AssertSuccess(StmtResult R) {
286212795Sdim    assert(!R.isInvalid() && "operation was asserted to never fail!");
287212795Sdim    return R.get();
288212795Sdim  }
289212795Sdim}
290212795Sdim
291212795Sdim#endif
292