Ownership.h 9.8 KB

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