Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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 LLVM_CLANG_AST_ABSTRACTBASICREADER_H
  10. #define LLVM_CLANG_AST_ABSTRACTBASICREADER_H
  11.  
  12. #include "clang/AST/DeclTemplate.h"
  13. #include <optional>
  14.  
  15. namespace clang {
  16. namespace serialization {
  17.  
  18. template <class T>
  19. inline T makeNullableFromOptional(const std::optional<T> &value) {
  20.   return (value ? *value : T());
  21. }
  22.  
  23. template <class T> inline T *makePointerFromOptional(std::optional<T *> value) {
  24.   return value.value_or(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. //   std::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.   std::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 origTy = asImpl().readQualType();
  194.     auto elemTy = origTy;
  195.     unsigned pathLength = asImpl().readUInt32();
  196.     for (unsigned i = 0; i < pathLength; ++i) {
  197.       if (elemTy->template getAs<RecordType>()) {
  198.         unsigned int_ = asImpl().readUInt32();
  199.         Decl *decl = asImpl().template readDeclAs<Decl>();
  200.         if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))
  201.           elemTy = getASTContext().getRecordType(recordDecl);
  202.         else
  203.           elemTy = cast<ValueDecl>(decl)->getType();
  204.         path.push_back(
  205.             APValue::LValuePathEntry(APValue::BaseOrMemberType(decl, int_)));
  206.       } else {
  207.         elemTy = getASTContext().getAsArrayType(elemTy)->getElementType();
  208.         path.push_back(
  209.             APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()));
  210.       }
  211.     }
  212.     return APValue::LValuePathSerializationHelper(path, origTy);
  213.   }
  214.  
  215.   Qualifiers readQualifiers() {
  216.     static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),
  217.                   "update this if the value size changes");
  218.     uint32_t value = asImpl().readUInt32();
  219.     return Qualifiers::fromOpaqueValue(value);
  220.   }
  221.  
  222.   FunctionProtoType::ExceptionSpecInfo
  223.   readExceptionSpecInfo(llvm::SmallVectorImpl<QualType> &buffer) {
  224.     FunctionProtoType::ExceptionSpecInfo esi;
  225.     esi.Type = ExceptionSpecificationType(asImpl().readUInt32());
  226.     if (esi.Type == EST_Dynamic) {
  227.       esi.Exceptions = asImpl().template readArray<QualType>(buffer);
  228.     } else if (isComputedNoexcept(esi.Type)) {
  229.       esi.NoexceptExpr = asImpl().readExprRef();
  230.     } else if (esi.Type == EST_Uninstantiated) {
  231.       esi.SourceDecl = asImpl().readFunctionDeclRef();
  232.       esi.SourceTemplate = asImpl().readFunctionDeclRef();
  233.     } else if (esi.Type == EST_Unevaluated) {
  234.       esi.SourceDecl = asImpl().readFunctionDeclRef();
  235.     }
  236.     return esi;
  237.   }
  238.  
  239.   FunctionProtoType::ExtParameterInfo readExtParameterInfo() {
  240.     static_assert(sizeof(FunctionProtoType::ExtParameterInfo().getOpaqueValue())
  241.                     <= sizeof(uint32_t),
  242.                   "opaque value doesn't fit into uint32_t");
  243.     uint32_t value = asImpl().readUInt32();
  244.     return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value);
  245.   }
  246.  
  247.   NestedNameSpecifier *readNestedNameSpecifier() {
  248.     auto &ctx = getASTContext();
  249.  
  250.     // We build this up iteratively.
  251.     NestedNameSpecifier *cur = nullptr;
  252.  
  253.     uint32_t depth = asImpl().readUInt32();
  254.     for (uint32_t i = 0; i != depth; ++i) {
  255.       auto kind = asImpl().readNestedNameSpecifierKind();
  256.       switch (kind) {
  257.       case NestedNameSpecifier::Identifier:
  258.         cur = NestedNameSpecifier::Create(ctx, cur,
  259.                                           asImpl().readIdentifier());
  260.         continue;
  261.  
  262.       case NestedNameSpecifier::Namespace:
  263.         cur = NestedNameSpecifier::Create(ctx, cur,
  264.                                           asImpl().readNamespaceDeclRef());
  265.         continue;
  266.  
  267.       case NestedNameSpecifier::NamespaceAlias:
  268.         cur = NestedNameSpecifier::Create(ctx, cur,
  269.                                      asImpl().readNamespaceAliasDeclRef());
  270.         continue;
  271.  
  272.       case NestedNameSpecifier::TypeSpec:
  273.       case NestedNameSpecifier::TypeSpecWithTemplate:
  274.         cur = NestedNameSpecifier::Create(ctx, cur,
  275.                           kind == NestedNameSpecifier::TypeSpecWithTemplate,
  276.                           asImpl().readQualType().getTypePtr());
  277.         continue;
  278.  
  279.       case NestedNameSpecifier::Global:
  280.         cur = NestedNameSpecifier::GlobalSpecifier(ctx);
  281.         continue;
  282.  
  283.       case NestedNameSpecifier::Super:
  284.         cur = NestedNameSpecifier::SuperSpecifier(ctx,
  285.                                             asImpl().readCXXRecordDeclRef());
  286.         continue;
  287.       }
  288.       llvm_unreachable("bad nested name specifier kind");
  289.     }
  290.  
  291.     return cur;
  292.   }
  293. };
  294.  
  295. } // end namespace serialization
  296. } // end namespace clang
  297.  
  298. #endif
  299.