Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:27

0001 //==--- AbstractBasiceReader.h - Abstract basic value deserialization -----===//
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 #ifndef LLVM_CLANG_AST_ABSTRACTBASICREADER_H
0010 #define LLVM_CLANG_AST_ABSTRACTBASICREADER_H
0011 
0012 #include "clang/AST/DeclTemplate.h"
0013 #include <optional>
0014 
0015 namespace clang {
0016 namespace serialization {
0017 
0018 template <class T>
0019 inline T makeNullableFromOptional(const std::optional<T> &value) {
0020   return (value ? *value : T());
0021 }
0022 
0023 template <class T> inline T *makePointerFromOptional(std::optional<T *> value) {
0024   return value.value_or(nullptr);
0025 }
0026 
0027 // PropertyReader is a class concept that requires the following method:
0028 //   BasicReader find(llvm::StringRef propertyName);
0029 // where BasicReader is some class conforming to the BasicReader concept.
0030 // An abstract AST-node reader is created with a PropertyReader and
0031 // performs a sequence of calls like so:
0032 //   propertyReader.find(propertyName).read##TypeName()
0033 // to read the properties of the node it is deserializing.
0034 
0035 // BasicReader is a class concept that requires methods like:
0036 //   ValueType read##TypeName();
0037 // where TypeName is the name of a PropertyType node from PropertiesBase.td
0038 // and ValueType is the corresponding C++ type name.  The read method may
0039 // require one or more buffer arguments.
0040 //
0041 // In addition to the concrete type names, BasicReader is expected to
0042 // implement these methods:
0043 //
0044 //   template <class EnumType>
0045 //   void writeEnum(T value);
0046 //
0047 //     Reads an enum value from the current property.  EnumType will always
0048 //     be an enum type.  Only necessary if the BasicReader doesn't provide
0049 //     type-specific readers for all the enum types.
0050 //
0051 //   template <class ValueType>
0052 //   std::optional<ValueType> writeOptional();
0053 //
0054 //     Reads an optional value from the current property.
0055 //
0056 //   template <class ValueType>
0057 //   ArrayRef<ValueType> readArray(llvm::SmallVectorImpl<ValueType> &buffer);
0058 //
0059 //     Reads an array of values from the current property.
0060 //
0061 //   PropertyReader readObject();
0062 //
0063 //     Reads an object from the current property; the returned property
0064 //     reader will be subjected to a sequence of property reads and then
0065 //     discarded before any other properties are reader from the "outer"
0066 //     property reader (which need not be the same type).  The sub-reader
0067 //     will be used as if with the following code:
0068 //
0069 //       {
0070 //         auto &&widget = W.find("widget").readObject();
0071 //         auto kind = widget.find("kind").readWidgetKind();
0072 //         auto declaration = widget.find("declaration").readDeclRef();
0073 //         return Widget(kind, declaration);
0074 //       }
0075 
0076 // ReadDispatcher does type-based forwarding to one of the read methods
0077 // on the BasicReader passed in:
0078 //
0079 // template <class ValueType>
0080 // struct ReadDispatcher {
0081 //   template <class BasicReader, class... BufferTypes>
0082 //   static ValueType read(BasicReader &R, BufferTypes &&...);
0083 // };
0084 
0085 // BasicReaderBase provides convenience implementations of the read methods
0086 // for EnumPropertyType and SubclassPropertyType types that just defer to
0087 // the "underlying" implementations (for UInt32 and the base class,
0088 // respectively).
0089 //
0090 // template <class Impl>
0091 // class BasicReaderBase {
0092 // protected:
0093 //   BasicReaderBase(ASTContext &ctx);
0094 //   Impl &asImpl();
0095 // public:
0096 //   ASTContext &getASTContext();
0097 //   ...
0098 // };
0099 
0100 // The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
0101 #include "clang/AST/AbstractBasicReader.inc"
0102 
0103 /// DataStreamBasicReader provides convenience implementations for many
0104 /// BasicReader methods based on the assumption that the
0105 /// ultimate reader implementation is based on a variable-length stream
0106 /// of unstructured data (like Clang's module files).  It is designed
0107 /// to pair with DataStreamBasicWriter.
0108 ///
0109 /// This class can also act as a PropertyReader, implementing find("...")
0110 /// by simply forwarding to itself.
0111 ///
0112 /// Unimplemented methods:
0113 ///   readBool
0114 ///   readUInt32
0115 ///   readUInt64
0116 ///   readIdentifier
0117 ///   readSelector
0118 ///   readSourceLocation
0119 ///   readQualType
0120 ///   readStmtRef
0121 ///   readDeclRef
0122 template <class Impl>
0123 class DataStreamBasicReader : public BasicReaderBase<Impl> {
0124 protected:
0125   using BasicReaderBase<Impl>::asImpl;
0126   DataStreamBasicReader(ASTContext &ctx) : BasicReaderBase<Impl>(ctx) {}
0127 
0128 public:
0129   using BasicReaderBase<Impl>::getASTContext;
0130 
0131   /// Implement property-find by ignoring it.  We rely on properties being
0132   /// serialized and deserialized in a reliable order instead.
0133   Impl &find(const char *propertyName) {
0134     return asImpl();
0135   }
0136 
0137   template <class T>
0138   T readEnum() {
0139     return T(asImpl().readUInt32());
0140   }
0141 
0142   // Implement object reading by forwarding to this, collapsing the
0143   // structure into a single data stream.
0144   Impl &readObject() { return asImpl(); }
0145 
0146   template <class T>
0147   llvm::ArrayRef<T> readArray(llvm::SmallVectorImpl<T> &buffer) {
0148     assert(buffer.empty());
0149 
0150     uint32_t size = asImpl().readUInt32();
0151     buffer.reserve(size);
0152 
0153     for (uint32_t i = 0; i != size; ++i) {
0154       buffer.push_back(ReadDispatcher<T>::read(asImpl()));
0155     }
0156     return buffer;
0157   }
0158 
0159   template <class T, class... Args>
0160   std::optional<T> readOptional(Args &&...args) {
0161     return UnpackOptionalValue<T>::unpack(
0162              ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
0163   }
0164 
0165   llvm::APSInt readAPSInt() {
0166     bool isUnsigned = asImpl().readBool();
0167     llvm::APInt value = asImpl().readAPInt();
0168     return llvm::APSInt(std::move(value), isUnsigned);
0169   }
0170 
0171   llvm::APInt readAPInt() {
0172     unsigned bitWidth = asImpl().readUInt32();
0173     unsigned numWords = llvm::APInt::getNumWords(bitWidth);
0174     llvm::SmallVector<uint64_t, 4> data;
0175     for (uint32_t i = 0; i != numWords; ++i)
0176       data.push_back(asImpl().readUInt64());
0177     return llvm::APInt(bitWidth, numWords, &data[0]);
0178   }
0179 
0180   llvm::FixedPointSemantics readFixedPointSemantics() {
0181     unsigned width = asImpl().readUInt32();
0182     unsigned scale = asImpl().readUInt32();
0183     unsigned tmp = asImpl().readUInt32();
0184     bool isSigned = tmp & 0x1;
0185     bool isSaturated = tmp & 0x2;
0186     bool hasUnsignedPadding = tmp & 0x4;
0187     return llvm::FixedPointSemantics(width, scale, isSigned, isSaturated,
0188                                      hasUnsignedPadding);
0189   }
0190 
0191   APValue::LValuePathSerializationHelper readLValuePathSerializationHelper(
0192       SmallVectorImpl<APValue::LValuePathEntry> &path) {
0193     auto origTy = asImpl().readQualType();
0194     auto elemTy = origTy;
0195     unsigned pathLength = asImpl().readUInt32();
0196     for (unsigned i = 0; i < pathLength; ++i) {
0197       if (elemTy->template getAs<RecordType>()) {
0198         unsigned int_ = asImpl().readUInt32();
0199         Decl *decl = asImpl().template readDeclAs<Decl>();
0200         if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))
0201           elemTy = getASTContext().getRecordType(recordDecl);
0202         else
0203           elemTy = cast<ValueDecl>(decl)->getType();
0204         path.push_back(
0205             APValue::LValuePathEntry(APValue::BaseOrMemberType(decl, int_)));
0206       } else {
0207         elemTy = getASTContext().getAsArrayType(elemTy)->getElementType();
0208         path.push_back(
0209             APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()));
0210       }
0211     }
0212     return APValue::LValuePathSerializationHelper(path, origTy);
0213   }
0214 
0215   Qualifiers readQualifiers() {
0216     static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint64_t),
0217                   "update this if the value size changes");
0218     uint64_t value = asImpl().readUInt64();
0219     return Qualifiers::fromOpaqueValue(value);
0220   }
0221 
0222   FunctionProtoType::ExceptionSpecInfo
0223   readExceptionSpecInfo(llvm::SmallVectorImpl<QualType> &buffer) {
0224     FunctionProtoType::ExceptionSpecInfo esi;
0225     esi.Type = ExceptionSpecificationType(asImpl().readUInt32());
0226     if (esi.Type == EST_Dynamic) {
0227       esi.Exceptions = asImpl().template readArray<QualType>(buffer);
0228     } else if (isComputedNoexcept(esi.Type)) {
0229       esi.NoexceptExpr = asImpl().readExprRef();
0230     } else if (esi.Type == EST_Uninstantiated) {
0231       esi.SourceDecl = asImpl().readFunctionDeclRef();
0232       esi.SourceTemplate = asImpl().readFunctionDeclRef();
0233     } else if (esi.Type == EST_Unevaluated) {
0234       esi.SourceDecl = asImpl().readFunctionDeclRef();
0235     }
0236     return esi;
0237   }
0238 
0239   FunctionProtoType::ExtParameterInfo readExtParameterInfo() {
0240     static_assert(sizeof(FunctionProtoType::ExtParameterInfo().getOpaqueValue())
0241                     <= sizeof(uint32_t),
0242                   "opaque value doesn't fit into uint32_t");
0243     uint32_t value = asImpl().readUInt32();
0244     return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value);
0245   }
0246 
0247   FunctionEffect readFunctionEffect() {
0248     uint32_t value = asImpl().readUInt32();
0249     return FunctionEffect::fromOpaqueInt32(value);
0250   }
0251 
0252   EffectConditionExpr readEffectConditionExpr() {
0253     return EffectConditionExpr{asImpl().readExprRef()};
0254   }
0255 
0256   NestedNameSpecifier *readNestedNameSpecifier() {
0257     auto &ctx = getASTContext();
0258 
0259     // We build this up iteratively.
0260     NestedNameSpecifier *cur = nullptr;
0261 
0262     uint32_t depth = asImpl().readUInt32();
0263     for (uint32_t i = 0; i != depth; ++i) {
0264       auto kind = asImpl().readNestedNameSpecifierKind();
0265       switch (kind) {
0266       case NestedNameSpecifier::Identifier:
0267         cur = NestedNameSpecifier::Create(ctx, cur,
0268                                           asImpl().readIdentifier());
0269         continue;
0270 
0271       case NestedNameSpecifier::Namespace:
0272         cur = NestedNameSpecifier::Create(ctx, cur,
0273                                           asImpl().readNamespaceDeclRef());
0274         continue;
0275 
0276       case NestedNameSpecifier::NamespaceAlias:
0277         cur = NestedNameSpecifier::Create(ctx, cur,
0278                                      asImpl().readNamespaceAliasDeclRef());
0279         continue;
0280 
0281       case NestedNameSpecifier::TypeSpec:
0282       case NestedNameSpecifier::TypeSpecWithTemplate:
0283         cur = NestedNameSpecifier::Create(ctx, cur,
0284                           kind == NestedNameSpecifier::TypeSpecWithTemplate,
0285                           asImpl().readQualType().getTypePtr());
0286         continue;
0287 
0288       case NestedNameSpecifier::Global:
0289         cur = NestedNameSpecifier::GlobalSpecifier(ctx);
0290         continue;
0291 
0292       case NestedNameSpecifier::Super:
0293         cur = NestedNameSpecifier::SuperSpecifier(ctx,
0294                                             asImpl().readCXXRecordDeclRef());
0295         continue;
0296       }
0297       llvm_unreachable("bad nested name specifier kind");
0298     }
0299 
0300     return cur;
0301   }
0302 };
0303 
0304 } // end namespace serialization
0305 } // end namespace clang
0306 
0307 #endif