Home | History | Annotate | Line # | Download | only in AST
      1 //==--- AbstractBasiceReader.h - Abstract basic value deserialization -----===//
      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 #ifndef CLANG_AST_ABSTRACTBASICREADER_H
     10 #define CLANG_AST_ABSTRACTBASICREADER_H
     11 
     12 #include "clang/AST/DeclTemplate.h"
     13 
     14 namespace clang {
     15 namespace serialization {
     16 
     17 template <class T>
     18 inline T makeNullableFromOptional(const Optional<T> &value) {
     19   return (value ? *value : T());
     20 }
     21 
     22 template <class T>
     23 inline T *makePointerFromOptional(Optional<T *> value) {
     24   return (value ? *value : nullptr);
     25 }
     26 
     27 // PropertyReader is a class concept that requires the following method:
     28 //   BasicReader find(llvm::StringRef propertyName);
     29 // where BasicReader is some class conforming to the BasicReader concept.
     30 // An abstract AST-node reader is created with a PropertyReader and
     31 // performs a sequence of calls like so:
     32 //   propertyReader.find(propertyName).read##TypeName()
     33 // to read the properties of the node it is deserializing.
     34 
     35 // BasicReader is a class concept that requires methods like:
     36 //   ValueType read##TypeName();
     37 // where TypeName is the name of a PropertyType node from PropertiesBase.td
     38 // and ValueType is the corresponding C++ type name.  The read method may
     39 // require one or more buffer arguments.
     40 //
     41 // In addition to the concrete type names, BasicReader is expected to
     42 // implement these methods:
     43 //
     44 //   template <class EnumType>
     45 //   void writeEnum(T value);
     46 //
     47 //     Reads an enum value from the current property.  EnumType will always
     48 //     be an enum type.  Only necessary if the BasicReader doesn't provide
     49 //     type-specific readers for all the enum types.
     50 //
     51 //   template <class ValueType>
     52 //   Optional<ValueType> writeOptional();
     53 //
     54 //     Reads an optional value from the current property.
     55 //
     56 //   template <class ValueType>
     57 //   ArrayRef<ValueType> readArray(llvm::SmallVectorImpl<ValueType> &buffer);
     58 //
     59 //     Reads an array of values from the current property.
     60 //
     61 //   PropertyReader readObject();
     62 //
     63 //     Reads an object from the current property; the returned property
     64 //     reader will be subjected to a sequence of property reads and then
     65 //     discarded before any other properties are reader from the "outer"
     66 //     property reader (which need not be the same type).  The sub-reader
     67 //     will be used as if with the following code:
     68 //
     69 //       {
     70 //         auto &&widget = W.find("widget").readObject();
     71 //         auto kind = widget.find("kind").readWidgetKind();
     72 //         auto declaration = widget.find("declaration").readDeclRef();
     73 //         return Widget(kind, declaration);
     74 //       }
     75 
     76 // ReadDispatcher does type-based forwarding to one of the read methods
     77 // on the BasicReader passed in:
     78 //
     79 // template <class ValueType>
     80 // struct ReadDispatcher {
     81 //   template <class BasicReader, class... BufferTypes>
     82 //   static ValueType read(BasicReader &R, BufferTypes &&...);
     83 // };
     84 
     85 // BasicReaderBase provides convenience implementations of the read methods
     86 // for EnumPropertyType and SubclassPropertyType types that just defer to
     87 // the "underlying" implementations (for UInt32 and the base class,
     88 // respectively).
     89 //
     90 // template <class Impl>
     91 // class BasicReaderBase {
     92 // protected:
     93 //   BasicReaderBase(ASTContext &ctx);
     94 //   Impl &asImpl();
     95 // public:
     96 //   ASTContext &getASTContext();
     97 //   ...
     98 // };
     99 
    100 // The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
    101 #include "clang/AST/AbstractBasicReader.inc"
    102 
    103 /// DataStreamBasicReader provides convenience implementations for many
    104 /// BasicReader methods based on the assumption that the
    105 /// ultimate reader implementation is based on a variable-length stream
    106 /// of unstructured data (like Clang's module files).  It is designed
    107 /// to pair with DataStreamBasicWriter.
    108 ///
    109 /// This class can also act as a PropertyReader, implementing find("...")
    110 /// by simply forwarding to itself.
    111 ///
    112 /// Unimplemented methods:
    113 ///   readBool
    114 ///   readUInt32
    115 ///   readUInt64
    116 ///   readIdentifier
    117 ///   readSelector
    118 ///   readSourceLocation
    119 ///   readQualType
    120 ///   readStmtRef
    121 ///   readDeclRef
    122 template <class Impl>
    123 class DataStreamBasicReader : public BasicReaderBase<Impl> {
    124 protected:
    125   using BasicReaderBase<Impl>::asImpl;
    126   DataStreamBasicReader(ASTContext &ctx) : BasicReaderBase<Impl>(ctx) {}
    127 
    128 public:
    129   using BasicReaderBase<Impl>::getASTContext;
    130 
    131   /// Implement property-find by ignoring it.  We rely on properties being
    132   /// serialized and deserialized in a reliable order instead.
    133   Impl &find(const char *propertyName) {
    134     return asImpl();
    135   }
    136 
    137   template <class T>
    138   T readEnum() {
    139     return T(asImpl().readUInt32());
    140   }
    141 
    142   // Implement object reading by forwarding to this, collapsing the
    143   // structure into a single data stream.
    144   Impl &readObject() { return asImpl(); }
    145 
    146   template <class T>
    147   llvm::ArrayRef<T> readArray(llvm::SmallVectorImpl<T> &buffer) {
    148     assert(buffer.empty());
    149 
    150     uint32_t size = asImpl().readUInt32();
    151     buffer.reserve(size);
    152 
    153     for (uint32_t i = 0; i != size; ++i) {
    154       buffer.push_back(ReadDispatcher<T>::read(asImpl()));
    155     }
    156     return buffer;
    157   }
    158 
    159   template <class T, class... Args>
    160   llvm::Optional<T> readOptional(Args &&...args) {
    161     return UnpackOptionalValue<T>::unpack(
    162              ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
    163   }
    164 
    165   llvm::APSInt readAPSInt() {
    166     bool isUnsigned = asImpl().readBool();
    167     llvm::APInt value = asImpl().readAPInt();
    168     return llvm::APSInt(std::move(value), isUnsigned);
    169   }
    170 
    171   llvm::APInt readAPInt() {
    172     unsigned bitWidth = asImpl().readUInt32();
    173     unsigned numWords = llvm::APInt::getNumWords(bitWidth);
    174     llvm::SmallVector<uint64_t, 4> data;
    175     for (uint32_t i = 0; i != numWords; ++i)
    176       data.push_back(asImpl().readUInt64());
    177     return llvm::APInt(bitWidth, numWords, &data[0]);
    178   }
    179 
    180   llvm::FixedPointSemantics readFixedPointSemantics() {
    181     unsigned width = asImpl().readUInt32();
    182     unsigned scale = asImpl().readUInt32();
    183     unsigned tmp = asImpl().readUInt32();
    184     bool isSigned = tmp & 0x1;
    185     bool isSaturated = tmp & 0x2;
    186     bool hasUnsignedPadding = tmp & 0x4;
    187     return llvm::FixedPointSemantics(width, scale, isSigned, isSaturated,
    188                                      hasUnsignedPadding);
    189   }
    190 
    191   APValue::LValuePathSerializationHelper readLValuePathSerializationHelper(
    192       SmallVectorImpl<APValue::LValuePathEntry> &path) {
    193     auto elemTy = asImpl().readQualType();
    194     unsigned pathLength = asImpl().readUInt32();
    195     for (unsigned i = 0; i < pathLength; ++i) {
    196       if (elemTy->template getAs<RecordType>()) {
    197         unsigned int_ = asImpl().readUInt32();
    198         Decl *decl = asImpl().template readDeclAs<Decl>();
    199         if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))
    200           elemTy = getASTContext().getRecordType(recordDecl);
    201         else
    202           elemTy = cast<ValueDecl>(decl)->getType();
    203         path.push_back(
    204             APValue::LValuePathEntry(APValue::BaseOrMemberType(decl, int_)));
    205       } else {
    206         elemTy = getASTContext().getAsArrayType(elemTy)->getElementType();
    207         path.push_back(
    208             APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()));
    209       }
    210     }
    211     return APValue::LValuePathSerializationHelper(path, elemTy);
    212   }
    213 
    214   Qualifiers readQualifiers() {
    215     static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),
    216                   "update this if the value size changes");
    217     uint32_t value = asImpl().readUInt32();
    218     return Qualifiers::fromOpaqueValue(value);
    219   }
    220 
    221   FunctionProtoType::ExceptionSpecInfo
    222   readExceptionSpecInfo(llvm::SmallVectorImpl<QualType> &buffer) {
    223     FunctionProtoType::ExceptionSpecInfo esi;
    224     esi.Type = ExceptionSpecificationType(asImpl().readUInt32());
    225     if (esi.Type == EST_Dynamic) {
    226       esi.Exceptions = asImpl().template readArray<QualType>(buffer);
    227     } else if (isComputedNoexcept(esi.Type)) {
    228       esi.NoexceptExpr = asImpl().readExprRef();
    229     } else if (esi.Type == EST_Uninstantiated) {
    230       esi.SourceDecl = asImpl().readFunctionDeclRef();
    231       esi.SourceTemplate = asImpl().readFunctionDeclRef();
    232     } else if (esi.Type == EST_Unevaluated) {
    233       esi.SourceDecl = asImpl().readFunctionDeclRef();
    234     }
    235     return esi;
    236   }
    237 
    238   FunctionProtoType::ExtParameterInfo readExtParameterInfo() {
    239     static_assert(sizeof(FunctionProtoType::ExtParameterInfo().getOpaqueValue())
    240                     <= sizeof(uint32_t),
    241                   "opaque value doesn't fit into uint32_t");
    242     uint32_t value = asImpl().readUInt32();
    243     return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value);
    244   }
    245 
    246   NestedNameSpecifier *readNestedNameSpecifier() {
    247     auto &ctx = getASTContext();
    248 
    249     // We build this up iteratively.
    250     NestedNameSpecifier *cur = nullptr;
    251 
    252     uint32_t depth = asImpl().readUInt32();
    253     for (uint32_t i = 0; i != depth; ++i) {
    254       auto kind = asImpl().readNestedNameSpecifierKind();
    255       switch (kind) {
    256       case NestedNameSpecifier::Identifier:
    257         cur = NestedNameSpecifier::Create(ctx, cur,
    258                                           asImpl().readIdentifier());
    259         continue;
    260 
    261       case NestedNameSpecifier::Namespace:
    262         cur = NestedNameSpecifier::Create(ctx, cur,
    263                                           asImpl().readNamespaceDeclRef());
    264         continue;
    265 
    266       case NestedNameSpecifier::NamespaceAlias:
    267         cur = NestedNameSpecifier::Create(ctx, cur,
    268                                      asImpl().readNamespaceAliasDeclRef());
    269         continue;
    270 
    271       case NestedNameSpecifier::TypeSpec:
    272       case NestedNameSpecifier::TypeSpecWithTemplate:
    273         cur = NestedNameSpecifier::Create(ctx, cur,
    274                           kind == NestedNameSpecifier::TypeSpecWithTemplate,
    275                           asImpl().readQualType().getTypePtr());
    276         continue;
    277 
    278       case NestedNameSpecifier::Global:
    279         cur = NestedNameSpecifier::GlobalSpecifier(ctx);
    280         continue;
    281 
    282       case NestedNameSpecifier::Super:
    283         cur = NestedNameSpecifier::SuperSpecifier(ctx,
    284                                             asImpl().readCXXRecordDeclRef());
    285         continue;
    286       }
    287       llvm_unreachable("bad nested name specifier kind");
    288     }
    289 
    290     return cur;
    291   }
    292 };
    293 
    294 } // end namespace serialization
    295 } // end namespace clang
    296 
    297 #endif
    298