1356843Sdim//==--- AbstractBasiceReader.h - Abstract basic value deserialization -----===// 2356843Sdim// 3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4356843Sdim// See https://llvm.org/LICENSE.txt for license information. 5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6356843Sdim// 7356843Sdim//===----------------------------------------------------------------------===// 8356843Sdim 9356843Sdim#ifndef CLANG_AST_ABSTRACTBASICREADER_H 10356843Sdim#define CLANG_AST_ABSTRACTBASICREADER_H 11356843Sdim 12356843Sdim#include "clang/AST/DeclTemplate.h" 13356843Sdim 14356843Sdimnamespace clang { 15356843Sdimnamespace serialization { 16356843Sdim 17356843Sdimtemplate <class T> 18356843Sdiminline T makeNullableFromOptional(const Optional<T> &value) { 19356843Sdim return (value ? *value : T()); 20356843Sdim} 21356843Sdim 22356843Sdimtemplate <class T> 23356843Sdiminline T *makePointerFromOptional(Optional<T *> value) { 24356843Sdim return (value ? *value : nullptr); 25356843Sdim} 26356843Sdim 27356843Sdim// PropertyReader is a class concept that requires the following method: 28356843Sdim// BasicReader find(llvm::StringRef propertyName); 29356843Sdim// where BasicReader is some class conforming to the BasicReader concept. 30356843Sdim// An abstract AST-node reader is created with a PropertyReader and 31356843Sdim// performs a sequence of calls like so: 32356843Sdim// propertyReader.find(propertyName).read##TypeName() 33356843Sdim// to read the properties of the node it is deserializing. 34356843Sdim 35356843Sdim// BasicReader is a class concept that requires methods like: 36356843Sdim// ValueType read##TypeName(); 37356843Sdim// where TypeName is the name of a PropertyType node from PropertiesBase.td 38356843Sdim// and ValueType is the corresponding C++ type name. The read method may 39356843Sdim// require one or more buffer arguments. 40356843Sdim// 41356843Sdim// In addition to the concrete type names, BasicReader is expected to 42356843Sdim// implement these methods: 43356843Sdim// 44356843Sdim// template <class EnumType> 45356843Sdim// void writeEnum(T value); 46356843Sdim// 47356843Sdim// Reads an enum value from the current property. EnumType will always 48356843Sdim// be an enum type. Only necessary if the BasicReader doesn't provide 49356843Sdim// type-specific readers for all the enum types. 50356843Sdim// 51356843Sdim// template <class ValueType> 52356843Sdim// Optional<ValueType> writeOptional(); 53356843Sdim// 54356843Sdim// Reads an optional value from the current property. 55356843Sdim// 56356843Sdim// template <class ValueType> 57356843Sdim// ArrayRef<ValueType> readArray(llvm::SmallVectorImpl<ValueType> &buffer); 58356843Sdim// 59356843Sdim// Reads an array of values from the current property. 60356843Sdim// 61356843Sdim// PropertyReader readObject(); 62356843Sdim// 63356843Sdim// Reads an object from the current property; the returned property 64356843Sdim// reader will be subjected to a sequence of property reads and then 65356843Sdim// discarded before any other properties are reader from the "outer" 66356843Sdim// property reader (which need not be the same type). The sub-reader 67356843Sdim// will be used as if with the following code: 68356843Sdim// 69356843Sdim// { 70356843Sdim// auto &&widget = W.find("widget").readObject(); 71356843Sdim// auto kind = widget.find("kind").readWidgetKind(); 72356843Sdim// auto declaration = widget.find("declaration").readDeclRef(); 73356843Sdim// return Widget(kind, declaration); 74356843Sdim// } 75356843Sdim 76356843Sdim// ReadDispatcher does type-based forwarding to one of the read methods 77356843Sdim// on the BasicReader passed in: 78356843Sdim// 79356843Sdim// template <class ValueType> 80356843Sdim// struct ReadDispatcher { 81356843Sdim// template <class BasicReader, class... BufferTypes> 82356843Sdim// static ValueType read(BasicReader &R, BufferTypes &&...); 83356843Sdim// }; 84356843Sdim 85356843Sdim// BasicReaderBase provides convenience implementations of the read methods 86356843Sdim// for EnumPropertyType and SubclassPropertyType types that just defer to 87356843Sdim// the "underlying" implementations (for UInt32 and the base class, 88356843Sdim// respectively). 89356843Sdim// 90356843Sdim// template <class Impl> 91356843Sdim// class BasicReaderBase { 92356843Sdim// protected: 93356843Sdim// BasicReaderBase(ASTContext &ctx); 94356843Sdim// Impl &asImpl(); 95356843Sdim// public: 96356843Sdim// ASTContext &getASTContext(); 97356843Sdim// ... 98356843Sdim// }; 99356843Sdim 100356843Sdim// The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp. 101356843Sdim#include "clang/AST/AbstractBasicReader.inc" 102356843Sdim 103356843Sdim/// DataStreamBasicReader provides convenience implementations for many 104356843Sdim/// BasicReader methods based on the assumption that the 105356843Sdim/// ultimate reader implementation is based on a variable-length stream 106356843Sdim/// of unstructured data (like Clang's module files). It is designed 107356843Sdim/// to pair with DataStreamBasicWriter. 108356843Sdim/// 109356843Sdim/// This class can also act as a PropertyReader, implementing find("...") 110356843Sdim/// by simply forwarding to itself. 111356843Sdim/// 112356843Sdim/// Unimplemented methods: 113356843Sdim/// readBool 114356843Sdim/// readUInt32 115356843Sdim/// readUInt64 116356843Sdim/// readIdentifier 117356843Sdim/// readSelector 118356843Sdim/// readSourceLocation 119356843Sdim/// readQualType 120356843Sdim/// readStmtRef 121356843Sdim/// readDeclRef 122356843Sdimtemplate <class Impl> 123356843Sdimclass DataStreamBasicReader : public BasicReaderBase<Impl> { 124356843Sdimprotected: 125356843Sdim using BasicReaderBase<Impl>::asImpl; 126356843Sdim DataStreamBasicReader(ASTContext &ctx) : BasicReaderBase<Impl>(ctx) {} 127356843Sdim 128356843Sdimpublic: 129356843Sdim using BasicReaderBase<Impl>::getASTContext; 130356843Sdim 131356843Sdim /// Implement property-find by ignoring it. We rely on properties being 132356843Sdim /// serialized and deserialized in a reliable order instead. 133356843Sdim Impl &find(const char *propertyName) { 134356843Sdim return asImpl(); 135356843Sdim } 136356843Sdim 137356843Sdim template <class T> 138356843Sdim T readEnum() { 139356843Sdim return T(asImpl().readUInt32()); 140356843Sdim } 141356843Sdim 142356843Sdim // Implement object reading by forwarding to this, collapsing the 143356843Sdim // structure into a single data stream. 144356843Sdim Impl &readObject() { return asImpl(); } 145356843Sdim 146356843Sdim template <class T> 147356843Sdim llvm::ArrayRef<T> readArray(llvm::SmallVectorImpl<T> &buffer) { 148356843Sdim assert(buffer.empty()); 149356843Sdim 150356843Sdim uint32_t size = asImpl().readUInt32(); 151356843Sdim buffer.reserve(size); 152356843Sdim 153356843Sdim for (uint32_t i = 0; i != size; ++i) { 154356843Sdim buffer.push_back(ReadDispatcher<T>::read(asImpl())); 155356843Sdim } 156356843Sdim return buffer; 157356843Sdim } 158356843Sdim 159356843Sdim template <class T, class... Args> 160356843Sdim llvm::Optional<T> readOptional(Args &&...args) { 161356843Sdim return UnpackOptionalValue<T>::unpack( 162356843Sdim ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...)); 163356843Sdim } 164356843Sdim 165356843Sdim llvm::APSInt readAPSInt() { 166356843Sdim bool isUnsigned = asImpl().readBool(); 167356843Sdim llvm::APInt value = asImpl().readAPInt(); 168356843Sdim return llvm::APSInt(std::move(value), isUnsigned); 169356843Sdim } 170356843Sdim 171356843Sdim llvm::APInt readAPInt() { 172356843Sdim unsigned bitWidth = asImpl().readUInt32(); 173356843Sdim unsigned numWords = llvm::APInt::getNumWords(bitWidth); 174356843Sdim llvm::SmallVector<uint64_t, 4> data; 175356843Sdim for (uint32_t i = 0; i != numWords; ++i) 176356843Sdim data.push_back(asImpl().readUInt64()); 177356843Sdim return llvm::APInt(bitWidth, numWords, &data[0]); 178356843Sdim } 179356843Sdim 180356843Sdim Qualifiers readQualifiers() { 181356843Sdim static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t), 182356843Sdim "update this if the value size changes"); 183356843Sdim uint32_t value = asImpl().readUInt32(); 184356843Sdim return Qualifiers::fromOpaqueValue(value); 185356843Sdim } 186356843Sdim 187356843Sdim FunctionProtoType::ExceptionSpecInfo 188356843Sdim readExceptionSpecInfo(llvm::SmallVectorImpl<QualType> &buffer) { 189356843Sdim FunctionProtoType::ExceptionSpecInfo esi; 190356843Sdim esi.Type = ExceptionSpecificationType(asImpl().readUInt32()); 191356843Sdim if (esi.Type == EST_Dynamic) { 192356843Sdim esi.Exceptions = asImpl().template readArray<QualType>(buffer); 193356843Sdim } else if (isComputedNoexcept(esi.Type)) { 194356843Sdim esi.NoexceptExpr = asImpl().readExprRef(); 195356843Sdim } else if (esi.Type == EST_Uninstantiated) { 196356843Sdim esi.SourceDecl = asImpl().readFunctionDeclRef(); 197356843Sdim esi.SourceTemplate = asImpl().readFunctionDeclRef(); 198356843Sdim } else if (esi.Type == EST_Unevaluated) { 199356843Sdim esi.SourceDecl = asImpl().readFunctionDeclRef(); 200356843Sdim } 201356843Sdim return esi; 202356843Sdim } 203356843Sdim 204356843Sdim FunctionProtoType::ExtParameterInfo readExtParameterInfo() { 205356843Sdim static_assert(sizeof(FunctionProtoType::ExtParameterInfo().getOpaqueValue()) 206356843Sdim <= sizeof(uint32_t), 207356843Sdim "opaque value doesn't fit into uint32_t"); 208356843Sdim uint32_t value = asImpl().readUInt32(); 209356843Sdim return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value); 210356843Sdim } 211356843Sdim 212356843Sdim NestedNameSpecifier *readNestedNameSpecifier() { 213356843Sdim auto &ctx = getASTContext(); 214356843Sdim 215356843Sdim // We build this up iteratively. 216356843Sdim NestedNameSpecifier *cur = nullptr; 217356843Sdim 218356843Sdim uint32_t depth = asImpl().readUInt32(); 219356843Sdim for (uint32_t i = 0; i != depth; ++i) { 220356843Sdim auto kind = asImpl().readNestedNameSpecifierKind(); 221356843Sdim switch (kind) { 222356843Sdim case NestedNameSpecifier::Identifier: 223356843Sdim cur = NestedNameSpecifier::Create(ctx, cur, 224356843Sdim asImpl().readIdentifier()); 225356843Sdim continue; 226356843Sdim 227356843Sdim case NestedNameSpecifier::Namespace: 228356843Sdim cur = NestedNameSpecifier::Create(ctx, cur, 229356843Sdim asImpl().readNamespaceDeclRef()); 230356843Sdim continue; 231356843Sdim 232356843Sdim case NestedNameSpecifier::NamespaceAlias: 233356843Sdim cur = NestedNameSpecifier::Create(ctx, cur, 234356843Sdim asImpl().readNamespaceAliasDeclRef()); 235356843Sdim continue; 236356843Sdim 237356843Sdim case NestedNameSpecifier::TypeSpec: 238356843Sdim case NestedNameSpecifier::TypeSpecWithTemplate: 239356843Sdim cur = NestedNameSpecifier::Create(ctx, cur, 240356843Sdim kind == NestedNameSpecifier::TypeSpecWithTemplate, 241356843Sdim asImpl().readQualType().getTypePtr()); 242356843Sdim continue; 243356843Sdim 244356843Sdim case NestedNameSpecifier::Global: 245356843Sdim cur = NestedNameSpecifier::GlobalSpecifier(ctx); 246356843Sdim continue; 247356843Sdim 248356843Sdim case NestedNameSpecifier::Super: 249356843Sdim cur = NestedNameSpecifier::SuperSpecifier(ctx, 250356843Sdim asImpl().readCXXRecordDeclRef()); 251356843Sdim continue; 252356843Sdim } 253356843Sdim llvm_unreachable("bad nested name specifier kind"); 254356843Sdim } 255356843Sdim 256356843Sdim return cur; 257356843Sdim } 258356843Sdim}; 259356843Sdim 260356843Sdim} // end namespace serialization 261356843Sdim} // end namespace clang 262356843Sdim 263356843Sdim#endif 264