xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/AbstractBasicReader.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //==--- AbstractBasicReader.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>
makeNullableFromOptional(const std::optional<T> & value)19 inline T makeNullableFromOptional(const std::optional<T> &value) {
20   return (value ? *value : T());
21 }
22 
makePointerFromOptional(std::optional<T * > value)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;
DataStreamBasicReader(ASTContext & ctx)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.
find(const char * propertyName)133   Impl &find(const char *propertyName) {
134     return asImpl();
135   }
136 
137   template <class T>
readEnum()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.
readObject()144   Impl &readObject() { return asImpl(); }
145 
readArray(llvm::SmallVectorImpl<T> & buffer)146   template <class T> ArrayRef<T> readArray(llvm::SmallVectorImpl<T> &buffer) {
147     assert(buffer.empty());
148 
149     uint32_t size = asImpl().readUInt32();
150     buffer.reserve(size);
151 
152     for (uint32_t i = 0; i != size; ++i) {
153       buffer.push_back(ReadDispatcher<T>::read(asImpl()));
154     }
155     return buffer;
156   }
157 
158   template <class T, class... Args>
readOptional(Args &&...args)159   std::optional<T> readOptional(Args &&...args) {
160     return UnpackOptionalValue<T>::unpack(
161              ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
162   }
163 
readAPSInt()164   llvm::APSInt readAPSInt() {
165     bool isUnsigned = asImpl().readBool();
166     llvm::APInt value = asImpl().readAPInt();
167     return llvm::APSInt(std::move(value), isUnsigned);
168   }
169 
readAPInt()170   llvm::APInt readAPInt() {
171     unsigned bitWidth = asImpl().readUInt32();
172     unsigned numWords = llvm::APInt::getNumWords(bitWidth);
173     llvm::SmallVector<uint64_t, 4> data;
174     for (uint32_t i = 0; i != numWords; ++i)
175       data.push_back(asImpl().readUInt64());
176     return llvm::APInt(bitWidth, numWords, &data[0]);
177   }
178 
readFixedPointSemantics()179   llvm::FixedPointSemantics readFixedPointSemantics() {
180     unsigned width = asImpl().readUInt32();
181     unsigned scale = asImpl().readUInt32();
182     unsigned tmp = asImpl().readUInt32();
183     bool isSigned = tmp & 0x1;
184     bool isSaturated = tmp & 0x2;
185     bool hasUnsignedPadding = tmp & 0x4;
186     return llvm::FixedPointSemantics(width, scale, isSigned, isSaturated,
187                                      hasUnsignedPadding);
188   }
189 
readLValuePathSerializationHelper(SmallVectorImpl<APValue::LValuePathEntry> & path)190   APValue::LValuePathSerializationHelper readLValuePathSerializationHelper(
191       SmallVectorImpl<APValue::LValuePathEntry> &path) {
192     auto origTy = asImpl().readQualType();
193     auto elemTy = origTy;
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, origTy);
212   }
213 
readQualifiers()214   Qualifiers readQualifiers() {
215     static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint64_t),
216                   "update this if the value size changes");
217     uint64_t value = asImpl().readUInt64();
218     return Qualifiers::fromOpaqueValue(value);
219   }
220 
221   FunctionProtoType::ExceptionSpecInfo
readExceptionSpecInfo(llvm::SmallVectorImpl<QualType> & buffer)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 
readExtParameterInfo()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 
readFunctionEffect()246   FunctionEffect readFunctionEffect() {
247     uint32_t value = asImpl().readUInt32();
248     return FunctionEffect::fromOpaqueInt32(value);
249   }
250 
readEffectConditionExpr()251   EffectConditionExpr readEffectConditionExpr() {
252     return EffectConditionExpr{asImpl().readExprRef()};
253   }
254 
readNestedNameSpecifier()255   NestedNameSpecifier *readNestedNameSpecifier() {
256     auto &ctx = getASTContext();
257 
258     // We build this up iteratively.
259     NestedNameSpecifier *cur = nullptr;
260 
261     uint32_t depth = asImpl().readUInt32();
262     for (uint32_t i = 0; i != depth; ++i) {
263       auto kind = asImpl().readNestedNameSpecifierKind();
264       switch (kind) {
265       case NestedNameSpecifier::Identifier:
266         cur = NestedNameSpecifier::Create(ctx, cur,
267                                           asImpl().readIdentifier());
268         continue;
269 
270       case NestedNameSpecifier::Namespace:
271         cur = NestedNameSpecifier::Create(ctx, cur,
272                                           asImpl().readNamespaceDeclRef());
273         continue;
274 
275       case NestedNameSpecifier::NamespaceAlias:
276         cur = NestedNameSpecifier::Create(ctx, cur,
277                                      asImpl().readNamespaceAliasDeclRef());
278         continue;
279 
280       case NestedNameSpecifier::TypeSpec:
281         cur = NestedNameSpecifier::Create(ctx, cur,
282                                           asImpl().readQualType().getTypePtr());
283         continue;
284 
285       case NestedNameSpecifier::Global:
286         cur = NestedNameSpecifier::GlobalSpecifier(ctx);
287         continue;
288 
289       case NestedNameSpecifier::Super:
290         cur = NestedNameSpecifier::SuperSpecifier(ctx,
291                                             asImpl().readCXXRecordDeclRef());
292         continue;
293       }
294       llvm_unreachable("bad nested name specifier kind");
295     }
296 
297     return cur;
298   }
299 };
300 
301 } // end namespace serialization
302 } // end namespace clang
303 
304 #endif
305