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
29namespace clang {
30
31class CXXBaseSpecifier;
32class CXXCtorInitializer;
33class Decl;
34class Expr;
35class ParsedTemplateArgument;
36class QualType;
37class Stmt;
38class TemplateName;
39class 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
53    explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {}
54
55    using Traits = llvm::PointerLikeTypeTraits<PtrTy>;
56
57  public:
58    OpaquePtr(std::nullptr_t = nullptr) {}
59
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*>.
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.
76    template <typename PtrT> PtrT getPtrAs() const {
77      return get();
78    }
79
80    PtrTy get() const {
81      return Traits::getFromVoidPointer(Ptr);
82    }
83
84    void set(PtrTy P) {
85      Ptr = Traits::getAsVoidPointer(P);
86    }
87
88    explicit operator bool() const { return Ptr != nullptr; }
89
90    void *getAsOpaquePtr() const { return Ptr; }
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
99    static UnionOpaquePtr make(OpaquePtr<T> P) {
100      UnionOpaquePtr OP = { P.getAsOpaquePtr() };
101      return OP;
102    }
103
104    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
115namespace 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
133namespace clang {
134
135class 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.
140template <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)
152template <class PtrTy, bool Compress = IsResultPtrLowBitFree<PtrTy>::value>
153class ActionResult {
154  PtrTy Val = {};
155  bool Invalid = false;
156
157public:
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.
181template <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
189public:
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.
229using ParsedType = OpaquePtr<QualType>;
230using 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.
235template <> struct IsResultPtrLowBitFree<Expr *> {
236  static const bool value = true;
237};
238template <> struct IsResultPtrLowBitFree<Stmt *> {
239  static const bool value = true;
240};
241template <> struct IsResultPtrLowBitFree<CXXBaseSpecifier *> {
242  static const bool value = true;
243};
244template <> struct IsResultPtrLowBitFree<CXXCtorInitializer *> {
245  static const bool value = true;
246};
247
248using ExprResult = ActionResult<Expr *>;
249using StmtResult = ActionResult<Stmt *>;
250using TypeResult = ActionResult<ParsedType>;
251using BaseResult = ActionResult<CXXBaseSpecifier *>;
252using MemInitResult = ActionResult<CXXCtorInitializer *>;
253
254using DeclResult = ActionResult<Decl *>;
255using ParsedTemplateTy = OpaquePtr<TemplateName>;
256using UnionParsedTemplateTy = UnionOpaquePtr<TemplateName>;
257
258using MultiExprArg = MutableArrayRef<Expr *>;
259using MultiStmtArg = MutableArrayRef<Stmt *>;
260using ASTTemplateArgsPtr = MutableArrayRef<ParsedTemplateArgument>;
261using MultiTypeArg = MutableArrayRef<ParsedType>;
262using MultiTemplateParamsArg = MutableArrayRef<TemplateParameterList *>;
263
264inline ExprResult ExprError() { return ExprResult(true); }
265inline StmtResult StmtError() { return StmtResult(true); }
266inline TypeResult TypeError() { return TypeResult(true); }
267
268inline ExprResult ExprError(const StreamingDiagnostic &) { return ExprError(); }
269inline StmtResult StmtError(const StreamingDiagnostic &) { return StmtError(); }
270
271inline ExprResult ExprEmpty() { return ExprResult(false); }
272inline StmtResult StmtEmpty() { return StmtResult(false); }
273
274inline Expr *AssertSuccess(ExprResult R) {
275  assert(!R.isInvalid() && "operation was asserted to never fail!");
276  return R.get();
277}
278
279inline 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