Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:00

0001 //===- Ownership.h - Parser ownership helpers -------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file contains classes for managing ownership of Stmt and Expr nodes.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_CLANG_SEMA_OWNERSHIP_H
0014 #define LLVM_CLANG_SEMA_OWNERSHIP_H
0015 
0016 #include "clang/AST/Expr.h"
0017 #include "clang/Basic/LLVM.h"
0018 #include "llvm/ADT/ArrayRef.h"
0019 #include "llvm/Support/PointerLikeTypeTraits.h"
0020 #include "llvm/Support/type_traits.h"
0021 #include <cassert>
0022 #include <cstddef>
0023 #include <cstdint>
0024 
0025 //===----------------------------------------------------------------------===//
0026 // OpaquePtr
0027 //===----------------------------------------------------------------------===//
0028 
0029 namespace clang {
0030 
0031 class CXXBaseSpecifier;
0032 class CXXCtorInitializer;
0033 class Decl;
0034 class Expr;
0035 class ParsedTemplateArgument;
0036 class QualType;
0037 class Stmt;
0038 class TemplateName;
0039 class TemplateParameterList;
0040 
0041   /// Wrapper for void* pointer.
0042   /// \tparam PtrTy Either a pointer type like 'T*' or a type that behaves like
0043   ///               a pointer.
0044   ///
0045   /// This is a very simple POD type that wraps a pointer that the Parser
0046   /// doesn't know about but that Sema or another client does.  The PtrTy
0047   /// template argument is used to make sure that "Decl" pointers are not
0048   /// compatible with "Type" pointers for example.
0049   template <class PtrTy>
0050   class OpaquePtr {
0051     void *Ptr = nullptr;
0052 
0053     explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {}
0054 
0055     using Traits = llvm::PointerLikeTypeTraits<PtrTy>;
0056 
0057   public:
0058     OpaquePtr(std::nullptr_t = nullptr) {}
0059 
0060     static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
0061 
0062     /// Returns plain pointer to the entity pointed by this wrapper.
0063     /// \tparam PointeeT Type of pointed entity.
0064     ///
0065     /// It is identical to getPtrAs<PointeeT*>.
0066     template <typename PointeeT> PointeeT* getPtrTo() const {
0067       return get();
0068     }
0069 
0070     /// Returns pointer converted to the specified type.
0071     /// \tparam PtrT Result pointer type.  There must be implicit conversion
0072     ///              from PtrTy to PtrT.
0073     ///
0074     /// In contrast to getPtrTo, this method allows the return type to be
0075     /// a smart pointer.
0076     template <typename PtrT> PtrT getPtrAs() const {
0077       return get();
0078     }
0079 
0080     PtrTy get() const {
0081       return Traits::getFromVoidPointer(Ptr);
0082     }
0083 
0084     void set(PtrTy P) {
0085       Ptr = Traits::getAsVoidPointer(P);
0086     }
0087 
0088     explicit operator bool() const { return Ptr != nullptr; }
0089 
0090     void *getAsOpaquePtr() const { return Ptr; }
0091     static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
0092   };
0093 
0094   /// UnionOpaquePtr - A version of OpaquePtr suitable for membership
0095   /// in a union.
0096   template <class T> struct UnionOpaquePtr {
0097     void *Ptr;
0098 
0099     static UnionOpaquePtr make(OpaquePtr<T> P) {
0100       UnionOpaquePtr OP = { P.getAsOpaquePtr() };
0101       return OP;
0102     }
0103 
0104     OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); }
0105     operator OpaquePtr<T>() const { return get(); }
0106 
0107     UnionOpaquePtr &operator=(OpaquePtr<T> P) {
0108       Ptr = P.getAsOpaquePtr();
0109       return *this;
0110     }
0111   };
0112 
0113 } // namespace clang
0114 
0115 namespace llvm {
0116 
0117   template <class T>
0118   struct PointerLikeTypeTraits<clang::OpaquePtr<T>> {
0119     static constexpr int NumLowBitsAvailable = 0;
0120 
0121     static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) {
0122       // FIXME: Doesn't work? return P.getAs< void >();
0123       return P.getAsOpaquePtr();
0124     }
0125 
0126     static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) {
0127       return clang::OpaquePtr<T>::getFromOpaquePtr(P);
0128     }
0129   };
0130 
0131 } // namespace llvm
0132 
0133 namespace clang {
0134 
0135 class StreamingDiagnostic;
0136 
0137 // Determines whether the low bit of the result pointer for the
0138 // given UID is always zero. If so, ActionResult will use that bit
0139 // for it's "invalid" flag.
0140 template <class Ptr> struct IsResultPtrLowBitFree {
0141   static const bool value = false;
0142 };
0143 
0144 /// The result of parsing/analyzing an expression, statement etc.
0145 ///
0146 /// It may be:
0147 /// - usable: a valid pointer to the result object
0148 /// - unset (null but valid): for constructs that may legitimately be absent
0149 ///   (for example, the condition of a for loop)
0150 /// - invalid: indicating an error
0151 ///   (no detail is provided, usually the error has already been diagnosed)
0152 template <class PtrTy, bool Compress = IsResultPtrLowBitFree<PtrTy>::value>
0153 class ActionResult {
0154   PtrTy Val = {};
0155   bool Invalid = false;
0156 
0157 public:
0158   ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {}
0159   ActionResult(PtrTy Val) { *this = Val; }
0160   ActionResult(const DiagnosticBuilder &) : ActionResult(/*Invalid=*/true) {}
0161 
0162   // These two overloads prevent void* -> bool conversions.
0163   ActionResult(const void *) = delete;
0164   ActionResult(volatile void *) = delete;
0165 
0166   bool isInvalid() const { return Invalid; }
0167   bool isUnset() const { return !Invalid && !Val; }
0168   bool isUsable() const { return !isInvalid() && !isUnset(); }
0169 
0170   PtrTy get() const { return Val; }
0171   template <typename T> T *getAs() { return static_cast<T *>(get()); }
0172 
0173   ActionResult &operator=(PtrTy RHS) {
0174     Val = RHS;
0175     Invalid = false;
0176     return *this;
0177   }
0178 };
0179 
0180 // If we PtrTy has a free bit, we can represent "invalid" as nullptr|1.
0181 template <typename PtrTy> class ActionResult<PtrTy, true> {
0182   static constexpr uintptr_t UnsetValue = 0x0;
0183   static constexpr uintptr_t InvalidValue = 0x1;
0184 
0185   uintptr_t Value = UnsetValue;
0186 
0187   using PtrTraits = llvm::PointerLikeTypeTraits<PtrTy>;
0188 
0189 public:
0190   ActionResult(bool Invalid = false)
0191       : Value(Invalid ? InvalidValue : UnsetValue) {}
0192   ActionResult(PtrTy V) { *this = V; }
0193   ActionResult(const DiagnosticBuilder &) : ActionResult(/*Invalid=*/true) {}
0194 
0195   // These two overloads prevent void* -> bool conversions.
0196   ActionResult(const void *) = delete;
0197   ActionResult(volatile void *) = delete;
0198 
0199   bool isInvalid() const { return Value == InvalidValue; }
0200   bool isUnset() const { return Value == UnsetValue; }
0201   bool isUsable() const { return !isInvalid() && !isUnset(); }
0202 
0203   PtrTy get() const {
0204     void *VP = reinterpret_cast<void *>(Value & ~0x01);
0205     return PtrTraits::getFromVoidPointer(VP);
0206   }
0207   template <typename T> T *getAs() { return static_cast<T *>(get()); }
0208 
0209   ActionResult &operator=(PtrTy RHS) {
0210     void *VP = PtrTraits::getAsVoidPointer(RHS);
0211     Value = reinterpret_cast<uintptr_t>(VP);
0212     assert((Value & 0x01) == 0 && "Badly aligned pointer");
0213     return *this;
0214   }
0215 
0216   // For types where we can fit a flag in with the pointer, provide
0217   // conversions to/from pointer type.
0218   static ActionResult getFromOpaquePointer(void *P) {
0219     ActionResult Result;
0220     Result.Value = (uintptr_t)P;
0221     assert(Result.isInvalid() ||
0222            PtrTraits::getAsVoidPointer(Result.get()) == P);
0223     return Result;
0224   }
0225   void *getAsOpaquePointer() const { return (void *)Value; }
0226 };
0227 
0228 /// An opaque type for threading parsed type information through the parser.
0229 using ParsedType = OpaquePtr<QualType>;
0230 using UnionParsedType = UnionOpaquePtr<QualType>;
0231 
0232 // We can re-use the low bit of expression, statement, base, and
0233 // member-initializer pointers for the "invalid" flag of
0234 // ActionResult.
0235 template <> struct IsResultPtrLowBitFree<Expr *> {
0236   static const bool value = true;
0237 };
0238 template <> struct IsResultPtrLowBitFree<Stmt *> {
0239   static const bool value = true;
0240 };
0241 template <> struct IsResultPtrLowBitFree<CXXBaseSpecifier *> {
0242   static const bool value = true;
0243 };
0244 template <> struct IsResultPtrLowBitFree<CXXCtorInitializer *> {
0245   static const bool value = true;
0246 };
0247 
0248 using ExprResult = ActionResult<Expr *>;
0249 using StmtResult = ActionResult<Stmt *>;
0250 using TypeResult = ActionResult<ParsedType>;
0251 using BaseResult = ActionResult<CXXBaseSpecifier *>;
0252 using MemInitResult = ActionResult<CXXCtorInitializer *>;
0253 
0254 using DeclResult = ActionResult<Decl *>;
0255 using ParsedTemplateTy = OpaquePtr<TemplateName>;
0256 using UnionParsedTemplateTy = UnionOpaquePtr<TemplateName>;
0257 
0258 using MultiExprArg = MutableArrayRef<Expr *>;
0259 using MultiStmtArg = MutableArrayRef<Stmt *>;
0260 using ASTTemplateArgsPtr = MutableArrayRef<ParsedTemplateArgument>;
0261 using MultiTypeArg = MutableArrayRef<ParsedType>;
0262 using MultiTemplateParamsArg = MutableArrayRef<TemplateParameterList *>;
0263 
0264 inline ExprResult ExprError() { return ExprResult(true); }
0265 inline StmtResult StmtError() { return StmtResult(true); }
0266 inline TypeResult TypeError() { return TypeResult(true); }
0267 
0268 inline ExprResult ExprError(const StreamingDiagnostic &) { return ExprError(); }
0269 inline StmtResult StmtError(const StreamingDiagnostic &) { return StmtError(); }
0270 
0271 inline ExprResult ExprEmpty() { return ExprResult(false); }
0272 inline StmtResult StmtEmpty() { return StmtResult(false); }
0273 
0274 inline Expr *AssertSuccess(ExprResult R) {
0275   assert(!R.isInvalid() && "operation was asserted to never fail!");
0276   return R.get();
0277 }
0278 
0279 inline Stmt *AssertSuccess(StmtResult R) {
0280   assert(!R.isInvalid() && "operation was asserted to never fail!");
0281   return R.get();
0282 }
0283 
0284 } // namespace clang
0285 
0286 #endif // LLVM_CLANG_SEMA_OWNERSHIP_H