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