Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

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

  1. //==--- AbstractBasicWriter.h - Abstract basic value serialization --------===//
  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_ABSTRACTBASICWRITER_H
  10. #define LLVM_CLANG_AST_ABSTRACTBASICWRITER_H
  11.  
  12. #include "clang/AST/ASTContext.h"
  13. #include "clang/AST/DeclTemplate.h"
  14. #include <optional>
  15.  
  16. namespace clang {
  17. namespace serialization {
  18.  
  19. template <class T>
  20. inline std::optional<T> makeOptionalFromNullable(const T &value) {
  21.   return (value.isNull() ? std::optional<T>() : std::optional<T>(value));
  22. }
  23.  
  24. template <class T> inline std::optional<T *> makeOptionalFromPointer(T *value) {
  25.   return (value ? std::optional<T *>(value) : std::optional<T *>());
  26. }
  27.  
  28. // PropertyWriter is a class concept that requires the following method:
  29. //   BasicWriter find(llvm::StringRef propertyName);
  30. // where BasicWriter is some class conforming to the BasicWriter concept.
  31. // An abstract AST-node writer is created with a PropertyWriter and
  32. // performs a sequence of calls like so:
  33. //   propertyWriter.find(propertyName).write##TypeName(value)
  34. // to write the properties of the node it is serializing.
  35.  
  36. // BasicWriter is a class concept that requires methods like:
  37. //   void write##TypeName(ValueType value);
  38. // where TypeName is the name of a PropertyType node from PropertiesBase.td
  39. // and ValueType is the corresponding C++ type name.
  40. //
  41. // In addition to the concrete property types, BasicWriter is expected
  42. // to implement these methods:
  43. //
  44. //   template <class EnumType>
  45. //   void writeEnum(T value);
  46. //
  47. //     Writes an enum value as the current property.  EnumType will always
  48. //     be an enum type.  Only necessary if the BasicWriter doesn't provide
  49. //     type-specific writers for all the enum types.
  50. //
  51. //   template <class ValueType>
  52. //   void writeOptional(std::optional<ValueType> value);
  53. //
  54. //     Writes an optional value as the current property.
  55. //
  56. //   template <class ValueType>
  57. //   void writeArray(ArrayRef<ValueType> value);
  58. //
  59. //     Writes an array of values as the current property.
  60. //
  61. //   PropertyWriter writeObject();
  62. //
  63. //     Writes an object as the current property; the returned property
  64. //     writer will be subjected to a sequence of property writes and then
  65. //     discarded before any other properties are written to the "outer"
  66. //     property writer (which need not be the same type).  The sub-writer
  67. //     will be used as if with the following code:
  68. //
  69. //       {
  70. //         auto &&widget = W.find("widget").writeObject();
  71. //         widget.find("kind").writeWidgetKind(...);
  72. //         widget.find("declaration").writeDeclRef(...);
  73. //       }
  74.  
  75. // WriteDispatcher is a template which does type-based forwarding to one
  76. // of the write methods of the BasicWriter passed in:
  77. //
  78. // template <class ValueType>
  79. // struct WriteDispatcher {
  80. //   template <class BasicWriter>
  81. //   static void write(BasicWriter &W, ValueType value);
  82. // };
  83.  
  84. // BasicWriterBase provides convenience implementations of the write
  85. // methods for EnumPropertyType and SubclassPropertyType types that just
  86. // defer to the "underlying" implementations (for UInt32 and the base class,
  87. // respectively).
  88. //
  89. // template <class Impl>
  90. // class BasicWriterBase {
  91. // protected:
  92. //   Impl &asImpl();
  93. // public:
  94. //   ...
  95. // };
  96.  
  97. // The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
  98. #include "clang/AST/AbstractBasicWriter.inc"
  99.  
  100. /// DataStreamBasicWriter provides convenience implementations for many
  101. /// BasicWriter methods based on the assumption that the
  102. /// ultimate writer implementation is based on a variable-length stream
  103. /// of unstructured data (like Clang's module files).  It is designed
  104. /// to pair with DataStreamBasicReader.
  105. ///
  106. /// This class can also act as a PropertyWriter, implementing find("...")
  107. /// by simply forwarding to itself.
  108. ///
  109. /// Unimplemented methods:
  110. ///   writeBool
  111. ///   writeUInt32
  112. ///   writeUInt64
  113. ///   writeIdentifier
  114. ///   writeSelector
  115. ///   writeSourceLocation
  116. ///   writeQualType
  117. ///   writeStmtRef
  118. ///   writeDeclRef
  119. template <class Impl>
  120. class DataStreamBasicWriter : public BasicWriterBase<Impl> {
  121. protected:
  122.   using BasicWriterBase<Impl>::asImpl;
  123.   DataStreamBasicWriter(ASTContext &ctx) : BasicWriterBase<Impl>(ctx) {}
  124.  
  125. public:
  126.   /// Implement property-find by ignoring it.  We rely on properties being
  127.   /// serialized and deserialized in a reliable order instead.
  128.   Impl &find(const char *propertyName) {
  129.     return asImpl();
  130.   }
  131.  
  132.   // Implement object writing by forwarding to this, collapsing the
  133.   // structure into a single data stream.
  134.   Impl &writeObject() { return asImpl(); }
  135.  
  136.   template <class T>
  137.   void writeEnum(T value) {
  138.     asImpl().writeUInt32(uint32_t(value));
  139.   }
  140.  
  141.   template <class T>
  142.   void writeArray(llvm::ArrayRef<T> array) {
  143.     asImpl().writeUInt32(array.size());
  144.     for (const T &elt : array) {
  145.       WriteDispatcher<T>::write(asImpl(), elt);
  146.     }
  147.   }
  148.  
  149.   template <class T> void writeOptional(std::optional<T> value) {
  150.     WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value));
  151.   }
  152.  
  153.   void writeAPSInt(const llvm::APSInt &value) {
  154.     asImpl().writeBool(value.isUnsigned());
  155.     asImpl().writeAPInt(value);
  156.   }
  157.  
  158.   void writeAPInt(const llvm::APInt &value) {
  159.     asImpl().writeUInt32(value.getBitWidth());
  160.     const uint64_t *words = value.getRawData();
  161.     for (size_t i = 0, e = value.getNumWords(); i != e; ++i)
  162.       asImpl().writeUInt64(words[i]);
  163.   }
  164.  
  165.   void writeFixedPointSemantics(const llvm::FixedPointSemantics &sema) {
  166.     asImpl().writeUInt32(sema.getWidth());
  167.     asImpl().writeUInt32(sema.getScale());
  168.     asImpl().writeUInt32(sema.isSigned() | sema.isSaturated() << 1 |
  169.                          sema.hasUnsignedPadding() << 2);
  170.   }
  171.  
  172.   void writeLValuePathSerializationHelper(
  173.       APValue::LValuePathSerializationHelper lvaluePath) {
  174.     ArrayRef<APValue::LValuePathEntry> path = lvaluePath.Path;
  175.     QualType elemTy = lvaluePath.getType();
  176.     asImpl().writeQualType(elemTy);
  177.     asImpl().writeUInt32(path.size());
  178.     auto &ctx = ((BasicWriterBase<Impl> *)this)->getASTContext();
  179.     for (auto elem : path) {
  180.       if (elemTy->getAs<RecordType>()) {
  181.         asImpl().writeUInt32(elem.getAsBaseOrMember().getInt());
  182.         const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer();
  183.         if (const auto *recordDecl = dyn_cast<CXXRecordDecl>(baseOrMember)) {
  184.           asImpl().writeDeclRef(recordDecl);
  185.           elemTy = ctx.getRecordType(recordDecl);
  186.         } else {
  187.           const auto *valueDecl = cast<ValueDecl>(baseOrMember);
  188.           asImpl().writeDeclRef(valueDecl);
  189.           elemTy = valueDecl->getType();
  190.         }
  191.       } else {
  192.         asImpl().writeUInt32(elem.getAsArrayIndex());
  193.         elemTy = ctx.getAsArrayType(elemTy)->getElementType();
  194.       }
  195.     }
  196.   }
  197.  
  198.   void writeQualifiers(Qualifiers value) {
  199.     static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t),
  200.                   "update this if the value size changes");
  201.     asImpl().writeUInt32(value.getAsOpaqueValue());
  202.   }
  203.  
  204.   void writeExceptionSpecInfo(
  205.                         const FunctionProtoType::ExceptionSpecInfo &esi) {
  206.     asImpl().writeUInt32(uint32_t(esi.Type));
  207.     if (esi.Type == EST_Dynamic) {
  208.       asImpl().writeArray(esi.Exceptions);
  209.     } else if (isComputedNoexcept(esi.Type)) {
  210.       asImpl().writeExprRef(esi.NoexceptExpr);
  211.     } else if (esi.Type == EST_Uninstantiated) {
  212.       asImpl().writeDeclRef(esi.SourceDecl);
  213.       asImpl().writeDeclRef(esi.SourceTemplate);
  214.     } else if (esi.Type == EST_Unevaluated) {
  215.       asImpl().writeDeclRef(esi.SourceDecl);
  216.     }
  217.   }
  218.  
  219.   void writeExtParameterInfo(FunctionProtoType::ExtParameterInfo epi) {
  220.     static_assert(sizeof(epi.getOpaqueValue()) <= sizeof(uint32_t),
  221.                   "opaque value doesn't fit into uint32_t");
  222.     asImpl().writeUInt32(epi.getOpaqueValue());
  223.   }
  224.  
  225.   void writeNestedNameSpecifier(NestedNameSpecifier *NNS) {
  226.     // Nested name specifiers usually aren't too long. I think that 8 would
  227.     // typically accommodate the vast majority.
  228.     SmallVector<NestedNameSpecifier *, 8> nestedNames;
  229.  
  230.     // Push each of the NNS's onto a stack for serialization in reverse order.
  231.     while (NNS) {
  232.       nestedNames.push_back(NNS);
  233.       NNS = NNS->getPrefix();
  234.     }
  235.  
  236.     asImpl().writeUInt32(nestedNames.size());
  237.     while (!nestedNames.empty()) {
  238.       NNS = nestedNames.pop_back_val();
  239.       NestedNameSpecifier::SpecifierKind kind = NNS->getKind();
  240.       asImpl().writeNestedNameSpecifierKind(kind);
  241.       switch (kind) {
  242.       case NestedNameSpecifier::Identifier:
  243.         asImpl().writeIdentifier(NNS->getAsIdentifier());
  244.         continue;
  245.  
  246.       case NestedNameSpecifier::Namespace:
  247.         asImpl().writeNamespaceDeclRef(NNS->getAsNamespace());
  248.         continue;
  249.  
  250.       case NestedNameSpecifier::NamespaceAlias:
  251.         asImpl().writeNamespaceAliasDeclRef(NNS->getAsNamespaceAlias());
  252.         continue;
  253.  
  254.       case NestedNameSpecifier::TypeSpec:
  255.       case NestedNameSpecifier::TypeSpecWithTemplate:
  256.         asImpl().writeQualType(QualType(NNS->getAsType(), 0));
  257.         continue;
  258.  
  259.       case NestedNameSpecifier::Global:
  260.         // Don't need to write an associated value.
  261.         continue;
  262.  
  263.       case NestedNameSpecifier::Super:
  264.         asImpl().writeDeclRef(NNS->getAsRecordDecl());
  265.         continue;
  266.       }
  267.       llvm_unreachable("bad nested name specifier kind");
  268.     }
  269.   }
  270. };
  271.  
  272. } // end namespace serialization
  273. } // end namespace clang
  274.  
  275. #endif
  276.