clang 22.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 LLVM_CLANG_AST_ABSTRACTBASICWRITER_H
10#define LLVM_CLANG_AST_ABSTRACTBASICWRITER_H
11
14#include <optional>
15
16namespace clang {
17namespace serialization {
18
19template <class T>
20inline std::optional<T> makeOptionalFromNullable(const T &value) {
21 return (value.isNull() ? std::optional<T>() : std::optional<T>(value));
22}
23
24template <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
119template <class Impl>
120class DataStreamBasicWriter : public BasicWriterBase<Impl> {
121protected:
122 using BasicWriterBase<Impl>::asImpl;
123 DataStreamBasicWriter(ASTContext &ctx) : BasicWriterBase<Impl>(ctx) {}
124
125public:
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> void writeArray(ArrayRef<T> array) {
142 asImpl().writeUInt32(array.size());
143 for (const T &elt : array) {
144 WriteDispatcher<T>::write(asImpl(), elt);
145 }
146 }
147
148 template <class T> void writeOptional(std::optional<T> value) {
149 WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value));
150 }
151
152 void writeAPSInt(const llvm::APSInt &value) {
153 asImpl().writeBool(value.isUnsigned());
154 asImpl().writeAPInt(value);
155 }
156
157 void writeAPInt(const llvm::APInt &value) {
158 asImpl().writeUInt32(value.getBitWidth());
159 const uint64_t *words = value.getRawData();
160 for (size_t i = 0, e = value.getNumWords(); i != e; ++i)
161 asImpl().writeUInt64(words[i]);
162 }
163
164 void writeFixedPointSemantics(const llvm::FixedPointSemantics &sema) {
165 asImpl().writeUInt32(sema.getWidth());
166 asImpl().writeUInt32(sema.getScale());
167 asImpl().writeUInt32(sema.isSigned() | sema.isSaturated() << 1 |
168 sema.hasUnsignedPadding() << 2);
169 }
170
174 QualType elemTy = lvaluePath.getType();
175 asImpl().writeQualType(elemTy);
176 asImpl().writeUInt32(path.size());
177 auto &ctx = ((BasicWriterBase<Impl> *)this)->getASTContext();
178 for (auto elem : path) {
179 if (elemTy->isRecordType()) {
180 asImpl().writeUInt32(elem.getAsBaseOrMember().getInt());
181 const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer();
182 if (const auto *recordDecl = dyn_cast<CXXRecordDecl>(baseOrMember)) {
183 asImpl().writeDeclRef(recordDecl);
184 elemTy = ctx.getCanonicalTagType(recordDecl);
185 } else {
186 const auto *valueDecl = cast<ValueDecl>(baseOrMember);
187 asImpl().writeDeclRef(valueDecl);
188 elemTy = valueDecl->getType();
189 }
190 } else {
191 asImpl().writeUInt32(elem.getAsArrayIndex());
192 elemTy = ctx.getAsArrayType(elemTy)->getElementType();
193 }
194 }
195 }
196
198 static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint64_t),
199 "update this if the value size changes");
200 asImpl().writeUInt64(value.getAsOpaqueValue());
201 }
202
205 asImpl().writeUInt32(uint32_t(esi.Type));
206 if (esi.Type == EST_Dynamic) {
207 asImpl().writeArray(esi.Exceptions);
208 } else if (isComputedNoexcept(esi.Type)) {
209 asImpl().writeExprRef(esi.NoexceptExpr);
210 } else if (esi.Type == EST_Uninstantiated) {
211 asImpl().writeDeclRef(esi.SourceDecl);
212 asImpl().writeDeclRef(esi.SourceTemplate);
213 } else if (esi.Type == EST_Unevaluated) {
214 asImpl().writeDeclRef(esi.SourceDecl);
215 }
216 }
217
219 static_assert(sizeof(epi.getOpaqueValue()) <= sizeof(uint32_t),
220 "opaque value doesn't fit into uint32_t");
221 asImpl().writeUInt32(epi.getOpaqueValue());
222 }
223
225 asImpl().writeUInt32(E.toOpaqueInt32());
226 }
227
229 asImpl().writeExprRef(CE.getCondition());
230 }
231
233 // Nested name specifiers usually aren't too long. I think that 8 would
234 // typically accommodate the vast majority.
236
237 // Push each of the NNS's onto a stack for serialization in reverse order.
238 while (NNS) {
239 nestedNames.push_back(NNS);
242 : std::nullopt;
243 }
244
245 asImpl().writeUInt32(nestedNames.size());
246 while (!nestedNames.empty()) {
247 NNS = nestedNames.pop_back_val();
249 asImpl().writeNestedNameSpecifierKind(kind);
250 switch (kind) {
252 asImpl().writeNamespaceBaseDeclRef(
254 continue;
256 asImpl().writeQualType(QualType(NNS.getAsType(), 0));
257 continue;
258
260 // Don't need to write an associated value.
261 continue;
262
264 asImpl().writeDeclRef(NNS.getAsMicrosoftSuper());
265 continue;
266
268 llvm_unreachable("unexpected null nested name specifier");
269 }
270 llvm_unreachable("bad nested name specifier kind");
271 }
272 }
273};
274
275} // end namespace serialization
276} // end namespace clang
277
278#endif
Defines the clang::ASTContext interface.
Expr * E
Defines the C++ template declaration subclasses.
ArrayRef< LValuePathEntry > Path
Definition: APValue.h:243
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
Wrap a function effect's condition expression in another struct so that FunctionProtoType's TrailingO...
Definition: TypeBase.h:5002
Expr * getCondition() const
Definition: TypeBase.h:5009
Represents an abstract function effect, using just an enumeration describing its kind.
Definition: TypeBase.h:4895
Interesting information about a specific parameter that can't simply be reflected in parameter's type...
Definition: TypeBase.h:4504
unsigned char getOpaqueValue() const
Definition: TypeBase.h:4553
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
CXXRecordDecl * getAsMicrosoftSuper() const
NamespaceAndPrefix getAsNamespaceAndPrefix() const
Kind
The kind of specifier that completes this nested name specifier.
@ MicrosoftSuper
Microsoft's '__super' specifier, stored as a CXXRecordDecl* of the class it appeared in.
@ Global
The global specifier '::'. There is no stored value.
@ Type
A type, stored as a Type*.
@ Namespace
A namespace-like entity, stored as a NamespaceBaseDecl*.
A (possibly-)qualified type.
Definition: TypeBase.h:937
The collection of all-type qualifiers we support.
Definition: TypeBase.h:331
uint64_t getAsOpaqueValue() const
Definition: TypeBase.h:455
bool isRecordType() const
Definition: TypeBase.h:8707
DataStreamBasicWriter provides convenience implementations for many BasicWriter methods based on the ...
void writeEffectConditionExpr(EffectConditionExpr CE)
void writeExceptionSpecInfo(const FunctionProtoType::ExceptionSpecInfo &esi)
void writeFixedPointSemantics(const llvm::FixedPointSemantics &sema)
void writeNestedNameSpecifier(NestedNameSpecifier NNS)
void writeOptional(std::optional< T > value)
void writeExtParameterInfo(FunctionProtoType::ExtParameterInfo epi)
Impl & find(const char *propertyName)
Implement property-find by ignoring it.
void writeAPSInt(const llvm::APSInt &value)
void writeLValuePathSerializationHelper(APValue::LValuePathSerializationHelper lvaluePath)
const internal::VariadicDynCastAllOfMatcher< Decl, ValueDecl > valueDecl
Matches any value declaration.
const internal::VariadicDynCastAllOfMatcher< Decl, RecordDecl > recordDecl
Matches class, struct, and union declarations.
std::optional< T > makeOptionalFromNullable(const T &value)
std::optional< T * > makeOptionalFromPointer(T *value)
The JSON file list parser is used to communicate input to InstallAPI.
bool isComputedNoexcept(ExceptionSpecificationType ESpecType)
const FunctionProtoType * T
@ EST_Uninstantiated
not instantiated yet
@ EST_Unevaluated
not evaluated yet, for special member function
@ EST_Dynamic
throw(T1, T2)
Holds information about the various types of exception specification.
Definition: TypeBase.h:5339
FunctionDecl * SourceDecl
The function whose exception specification this is, for EST_Unevaluated and EST_Uninstantiated.
Definition: TypeBase.h:5351
FunctionDecl * SourceTemplate
The function template whose exception specification this is instantiated from, for EST_Uninstantiated...
Definition: TypeBase.h:5355
ExceptionSpecificationType Type
The kind of exception specification this is.
Definition: TypeBase.h:5341
ArrayRef< QualType > Exceptions
Explicitly-specified list of exception types.
Definition: TypeBase.h:5344
Expr * NoexceptExpr
Noexcept expression, if this is a computed noexcept specification.
Definition: TypeBase.h:5347
const NamespaceBaseDecl * Namespace