1 //===- Ownership.h - Parser ownership helpers -------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file contains classes for managing ownership of Stmt and Expr nodes.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_SEMA_OWNERSHIP_H
14 #define LLVM_CLANG_SEMA_OWNERSHIP_H
15 
16 #include "clang/AST/Expr.h"
17 #include "clang/Basic/LLVM.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/Support/PointerLikeTypeTraits.h"
20 #include "llvm/Support/type_traits.h"
21 #include <cassert>
22 #include <cstddef>
23 #include <cstdint>
24 
25 //===----------------------------------------------------------------------===//
26 // OpaquePtr
27 //===----------------------------------------------------------------------===//
28 
29 namespace clang {
30 
31 class CXXBaseSpecifier;
32 class CXXCtorInitializer;
33 class Decl;
34 class Expr;
35 class ParsedTemplateArgument;
36 class QualType;
37 class Stmt;
38 class TemplateName;
39 class TemplateParameterList;
40 
41   /// Wrapper for void* pointer.
42   /// \tparam PtrTy Either a pointer type like 'T*' or a type that behaves like
43   ///               a pointer.
44   ///
45   /// This is a very simple POD type that wraps a pointer that the Parser
46   /// doesn't know about but that Sema or another client does.  The PtrTy
47   /// template argument is used to make sure that "Decl" pointers are not
48   /// compatible with "Type" pointers for example.
49   template <class PtrTy>
50   class OpaquePtr {
51     void *Ptr = nullptr;
52 
OpaquePtr(void * Ptr)53     explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {}
54 
55     using Traits = llvm::PointerLikeTypeTraits<PtrTy>;
56 
57   public:
58     OpaquePtr(std::nullptr_t = nullptr) {}
59 
make(PtrTy P)60     static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
61 
62     /// Returns plain pointer to the entity pointed by this wrapper.
63     /// \tparam PointeeT Type of pointed entity.
64     ///
65     /// It is identical to getPtrAs<PointeeT*>.
getPtrTo()66     template <typename PointeeT> PointeeT* getPtrTo() const {
67       return get();
68     }
69 
70     /// Returns pointer converted to the specified type.
71     /// \tparam PtrT Result pointer type.  There must be implicit conversion
72     ///              from PtrTy to PtrT.
73     ///
74     /// In contrast to getPtrTo, this method allows the return type to be
75     /// a smart pointer.
getPtrAs()76     template <typename PtrT> PtrT getPtrAs() const {
77       return get();
78     }
79 
get()80     PtrTy get() const {
81       return Traits::getFromVoidPointer(Ptr);
82     }
83 
set(PtrTy P)84     void set(PtrTy P) {
85       Ptr = Traits::getAsVoidPointer(P);
86     }
87 
88     explicit operator bool() const { return Ptr != nullptr; }
89 
getAsOpaquePtr()90     void *getAsOpaquePtr() const { return Ptr; }
getFromOpaquePtr(void * P)91     static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
92   };
93 
94   /// UnionOpaquePtr - A version of OpaquePtr suitable for membership
95   /// in a union.
96   template <class T> struct UnionOpaquePtr {
97     void *Ptr;
98 
makeUnionOpaquePtr99     static UnionOpaquePtr make(OpaquePtr<T> P) {
100       UnionOpaquePtr OP = { P.getAsOpaquePtr() };
101       return OP;
102     }
103 
getUnionOpaquePtr104     OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); }
105     operator OpaquePtr<T>() const { return get(); }
106 
107     UnionOpaquePtr &operator=(OpaquePtr<T> P) {
108       Ptr = P.getAsOpaquePtr();
109       return *this;
110     }
111   };
112 
113 } // namespace clang
114 
115 namespace llvm {
116 
117   template <class T>
118   struct PointerLikeTypeTraits<clang::OpaquePtr<T>> {
119     static constexpr int NumLowBitsAvailable = 0;
120 
121     static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) {
122       // FIXME: Doesn't work? return P.getAs< void >();
123       return P.getAsOpaquePtr();
124     }
125 
126     static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) {
127       return clang::OpaquePtr<T>::getFromOpaquePtr(P);
128     }
129   };
130 
131 } // namespace llvm
132 
133 namespace clang {
134 
135 class StreamingDiagnostic;
136 
137 // Determines whether the low bit of the result pointer for the
138 // given UID is always zero. If so, ActionResult will use that bit
139 // for it's "invalid" flag.
140 template <class Ptr> struct IsResultPtrLowBitFree {
141   static const bool value = false;
142 };
143 
144 /// The result of parsing/analyzing an expression, statement etc.
145 ///
146 /// It may be:
147 /// - usable: a valid pointer to the result object
148 /// - unset (null but valid): for constructs that may legitimately be absent
149 ///   (for example, the condition of a for loop)
150 /// - invalid: indicating an error
151 ///   (no detail is provided, usually the error has already been diagnosed)
152 template <class PtrTy, bool Compress = IsResultPtrLowBitFree<PtrTy>::value>
153 class ActionResult {
154   PtrTy Val = {};
155   bool Invalid = false;
156 
157 public:
158   ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {}
159   ActionResult(PtrTy Val) { *this = Val; }
160   ActionResult(const DiagnosticBuilder &) : ActionResult(/*Invalid=*/true) {}
161 
162   // These two overloads prevent void* -> bool conversions.
163   ActionResult(const void *) = delete;
164   ActionResult(volatile void *) = delete;
165 
166   bool isInvalid() const { return Invalid; }
167   bool isUnset() const { return !Invalid && !Val; }
168   bool isUsable() const { return !isInvalid() && !isUnset(); }
169 
170   PtrTy get() const { return Val; }
171   template <typename T> T *getAs() { return static_cast<T *>(get()); }
172 
173   ActionResult &operator=(PtrTy RHS) {
174     Val = RHS;
175     Invalid = false;
176     return *this;
177   }
178 };
179 
180 // If we PtrTy has a free bit, we can represent "invalid" as nullptr|1.
181 template <typename PtrTy> class ActionResult<PtrTy, true> {
182   static constexpr uintptr_t UnsetValue = 0x0;
183   static constexpr uintptr_t InvalidValue = 0x1;
184 
185   uintptr_t Value = UnsetValue;
186 
187   using PtrTraits = llvm::PointerLikeTypeTraits<PtrTy>;
188 
189 public:
190   ActionResult(bool Invalid = false)
191       : Value(Invalid ? InvalidValue : UnsetValue) {}
192   ActionResult(PtrTy V) { *this = V; }
193   ActionResult(const DiagnosticBuilder &) : ActionResult(/*Invalid=*/true) {}
194 
195   // These two overloads prevent void* -> bool conversions.
196   ActionResult(const void *) = delete;
197   ActionResult(volatile void *) = delete;
198 
199   bool isInvalid() const { return Value == InvalidValue; }
200   bool isUnset() const { return Value == UnsetValue; }
201   bool isUsable() const { return !isInvalid() && !isUnset(); }
202 
203   PtrTy get() const {
204     void *VP = reinterpret_cast<void *>(Value & ~0x01);
205     return PtrTraits::getFromVoidPointer(VP);
206   }
207   template <typename T> T *getAs() { return static_cast<T *>(get()); }
208 
209   ActionResult &operator=(PtrTy RHS) {
210     void *VP = PtrTraits::getAsVoidPointer(RHS);
211     Value = reinterpret_cast<uintptr_t>(VP);
212     assert((Value & 0x01) == 0 && "Badly aligned pointer");
213     return *this;
214   }
215 
216   // For types where we can fit a flag in with the pointer, provide
217   // conversions to/from pointer type.
218   static ActionResult getFromOpaquePointer(void *P) {
219     ActionResult Result;
220     Result.Value = (uintptr_t)P;
221     assert(Result.isInvalid() ||
222            PtrTraits::getAsVoidPointer(Result.get()) == P);
223     return Result;
224   }
225   void *getAsOpaquePointer() const { return (void *)Value; }
226 };
227 
228 /// An opaque type for threading parsed type information through the parser.
229 using ParsedType = OpaquePtr<QualType>;
230 using UnionParsedType = UnionOpaquePtr<QualType>;
231 
232 // We can re-use the low bit of expression, statement, base, and
233 // member-initializer pointers for the "invalid" flag of
234 // ActionResult.
235 template <> struct IsResultPtrLowBitFree<Expr *> {
236   static const bool value = true;
237 };
238 template <> struct IsResultPtrLowBitFree<Stmt *> {
239   static const bool value = true;
240 };
241 template <> struct IsResultPtrLowBitFree<CXXBaseSpecifier *> {
242   static const bool value = true;
243 };
244 template <> struct IsResultPtrLowBitFree<CXXCtorInitializer *> {
245   static const bool value = true;
246 };
247 
248 using ExprResult = ActionResult<Expr *>;
249 using StmtResult = ActionResult<Stmt *>;
250 using TypeResult = ActionResult<ParsedType>;
251 using BaseResult = ActionResult<CXXBaseSpecifier *>;
252 using MemInitResult = ActionResult<CXXCtorInitializer *>;
253 
254 using DeclResult = ActionResult<Decl *>;
255 using ParsedTemplateTy = OpaquePtr<TemplateName>;
256 using UnionParsedTemplateTy = UnionOpaquePtr<TemplateName>;
257 
258 using MultiExprArg = MutableArrayRef<Expr *>;
259 using MultiStmtArg = MutableArrayRef<Stmt *>;
260 using ASTTemplateArgsPtr = MutableArrayRef<ParsedTemplateArgument>;
261 using MultiTypeArg = MutableArrayRef<ParsedType>;
262 using MultiTemplateParamsArg = MutableArrayRef<TemplateParameterList *>;
263 
264 inline ExprResult ExprError() { return ExprResult(true); }
265 inline StmtResult StmtError() { return StmtResult(true); }
266 inline TypeResult TypeError() { return TypeResult(true); }
267 
268 inline ExprResult ExprError(const StreamingDiagnostic &) { return ExprError(); }
269 inline StmtResult StmtError(const StreamingDiagnostic &) { return StmtError(); }
270 
271 inline ExprResult ExprEmpty() { return ExprResult(false); }
272 inline StmtResult StmtEmpty() { return StmtResult(false); }
273 
274 inline Expr *AssertSuccess(ExprResult R) {
275   assert(!R.isInvalid() && "operation was asserted to never fail!");
276   return R.get();
277 }
278 
279 inline Stmt *AssertSuccess(StmtResult R) {
280   assert(!R.isInvalid() && "operation was asserted to never fail!");
281   return R.get();
282 }
283 
284 } // namespace clang
285 
286 #endif // LLVM_CLANG_SEMA_OWNERSHIP_H
287