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