Home | History | Annotate | Line # | Download | only in Sema
      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 
     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 
    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   // Basic
    136 class StreamingDiagnostic;
    137 
    138 // Determines whether the low bit of the result pointer for the
    139 // given UID is always zero. If so, ActionResult will use that bit
    140 // for it's "invalid" flag.
    141 template <class Ptr> struct IsResultPtrLowBitFree {
    142   static const bool value = false;
    143   };
    144 
    145   /// ActionResult - This structure is used while parsing/acting on
    146   /// expressions, stmts, etc.  It encapsulates both the object returned by
    147   /// the action, plus a sense of whether or not it is valid.
    148   /// When CompressInvalid is true, the "invalid" flag will be
    149   /// stored in the low bit of the Val pointer.
    150   template<class PtrTy,
    151            bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value>
    152   class ActionResult {
    153     PtrTy Val;
    154     bool Invalid;
    155 
    156   public:
    157     ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {}
    158     ActionResult(PtrTy val) : Val(val), Invalid(false) {}
    159     ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
    160 
    161     // These two overloads prevent void* -> bool conversions.
    162     ActionResult(const void *) = delete;
    163     ActionResult(volatile void *) = delete;
    164 
    165     bool isInvalid() const { return Invalid; }
    166     bool isUsable() const { return !Invalid && Val; }
    167     bool isUnset() const { return !Invalid && !Val; }
    168 
    169     PtrTy get() const { return Val; }
    170     template <typename T> T *getAs() { return static_cast<T*>(get()); }
    171 
    172     void set(PtrTy V) { Val = V; }
    173 
    174     const ActionResult &operator=(PtrTy RHS) {
    175       Val = RHS;
    176       Invalid = false;
    177       return *this;
    178     }
    179   };
    180 
    181   // This ActionResult partial specialization places the "invalid"
    182   // flag into the low bit of the pointer.
    183   template<typename PtrTy>
    184   class ActionResult<PtrTy, true> {
    185     // A pointer whose low bit is 1 if this result is invalid, 0
    186     // otherwise.
    187     uintptr_t PtrWithInvalid;
    188 
    189     using PtrTraits = llvm::PointerLikeTypeTraits<PtrTy>;
    190 
    191   public:
    192     ActionResult(bool Invalid = false)
    193         : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) {}
    194 
    195     ActionResult(PtrTy V) {
    196       void *VP = PtrTraits::getAsVoidPointer(V);
    197       PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
    198       assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
    199     }
    200 
    201     ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) {}
    202 
    203     // These two overloads prevent void* -> bool conversions.
    204     ActionResult(const void *) = delete;
    205     ActionResult(volatile void *) = delete;
    206 
    207     bool isInvalid() const { return PtrWithInvalid & 0x01; }
    208     bool isUsable() const { return PtrWithInvalid > 0x01; }
    209     bool isUnset() const { return PtrWithInvalid == 0; }
    210 
    211     PtrTy get() const {
    212       void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
    213       return PtrTraits::getFromVoidPointer(VP);
    214     }
    215 
    216     template <typename T> T *getAs() { return static_cast<T*>(get()); }
    217 
    218     void set(PtrTy V) {
    219       void *VP = PtrTraits::getAsVoidPointer(V);
    220       PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
    221       assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
    222     }
    223 
    224     const ActionResult &operator=(PtrTy RHS) {
    225       void *VP = PtrTraits::getAsVoidPointer(RHS);
    226       PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
    227       assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
    228       return *this;
    229     }
    230 
    231     // For types where we can fit a flag in with the pointer, provide
    232     // conversions to/from pointer type.
    233     static ActionResult getFromOpaquePointer(void *P) {
    234       ActionResult Result;
    235       Result.PtrWithInvalid = (uintptr_t)P;
    236       return Result;
    237     }
    238     void *getAsOpaquePointer() const { return (void*)PtrWithInvalid; }
    239   };
    240 
    241   /// An opaque type for threading parsed type information through the
    242   /// parser.
    243   using ParsedType = OpaquePtr<QualType>;
    244   using UnionParsedType = UnionOpaquePtr<QualType>;
    245 
    246   // We can re-use the low bit of expression, statement, base, and
    247   // member-initializer pointers for the "invalid" flag of
    248   // ActionResult.
    249   template<> struct IsResultPtrLowBitFree<Expr*> {
    250     static const bool value = true;
    251   };
    252   template<> struct IsResultPtrLowBitFree<Stmt*> {
    253     static const bool value = true;
    254   };
    255   template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> {
    256     static const bool value = true;
    257   };
    258   template<> struct IsResultPtrLowBitFree<CXXCtorInitializer*> {
    259     static const bool value = true;
    260   };
    261 
    262   using ExprResult = ActionResult<Expr *>;
    263   using StmtResult = ActionResult<Stmt *>;
    264   using TypeResult = ActionResult<ParsedType>;
    265   using BaseResult = ActionResult<CXXBaseSpecifier *>;
    266   using MemInitResult = ActionResult<CXXCtorInitializer *>;
    267 
    268   using DeclResult = ActionResult<Decl *>;
    269   using ParsedTemplateTy = OpaquePtr<TemplateName>;
    270   using UnionParsedTemplateTy = UnionOpaquePtr<TemplateName>;
    271 
    272   using MultiExprArg = MutableArrayRef<Expr *>;
    273   using MultiStmtArg = MutableArrayRef<Stmt *>;
    274   using ASTTemplateArgsPtr = MutableArrayRef<ParsedTemplateArgument>;
    275   using MultiTypeArg = MutableArrayRef<ParsedType>;
    276   using MultiTemplateParamsArg = MutableArrayRef<TemplateParameterList *>;
    277 
    278   inline ExprResult ExprError() { return ExprResult(true); }
    279   inline StmtResult StmtError() { return StmtResult(true); }
    280   inline TypeResult TypeError() { return TypeResult(true); }
    281 
    282   inline ExprResult ExprError(const StreamingDiagnostic &) {
    283     return ExprError();
    284   }
    285   inline StmtResult StmtError(const StreamingDiagnostic &) {
    286     return StmtError();
    287   }
    288 
    289   inline ExprResult ExprEmpty() { return ExprResult(false); }
    290   inline StmtResult StmtEmpty() { return StmtResult(false); }
    291 
    292   inline Expr *AssertSuccess(ExprResult R) {
    293     assert(!R.isInvalid() && "operation was asserted to never fail!");
    294     return R.get();
    295   }
    296 
    297   inline Stmt *AssertSuccess(StmtResult R) {
    298     assert(!R.isInvalid() && "operation was asserted to never fail!");
    299     return R.get();
    300   }
    301 
    302 } // namespace clang
    303 
    304 #endif // LLVM_CLANG_SEMA_OWNERSHIP_H
    305