clang  12.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/DeclTemplate.h"
13 
14 namespace clang {
15 namespace serialization {
16 
17 template <class T>
19  return (value.isNull()
21  : llvm::Optional<T>(value));
22 }
23 
24 template <class T>
26  return (value ? llvm::Optional<T*>(value) : llvm::Optional<T*>());
27 }
28 
29 // PropertyWriter is a class concept that requires the following method:
30 // BasicWriter find(llvm::StringRef propertyName);
31 // where BasicWriter is some class conforming to the BasicWriter concept.
32 // An abstract AST-node writer is created with a PropertyWriter and
33 // performs a sequence of calls like so:
34 // propertyWriter.find(propertyName).write##TypeName(value)
35 // to write the properties of the node it is serializing.
36 
37 // BasicWriter is a class concept that requires methods like:
38 // void write##TypeName(ValueType value);
39 // where TypeName is the name of a PropertyType node from PropertiesBase.td
40 // and ValueType is the corresponding C++ type name.
41 //
42 // In addition to the concrete property types, BasicWriter is expected
43 // to implement these methods:
44 //
45 // template <class EnumType>
46 // void writeEnum(T value);
47 //
48 // Writes an enum value as the current property. EnumType will always
49 // be an enum type. Only necessary if the BasicWriter doesn't provide
50 // type-specific writers for all the enum types.
51 //
52 // template <class ValueType>
53 // void writeOptional(Optional<ValueType> value);
54 //
55 // Writes an optional value as the current property.
56 //
57 // template <class ValueType>
58 // void writeArray(ArrayRef<ValueType> value);
59 //
60 // Writes an array of values as the current property.
61 //
62 // PropertyWriter writeObject();
63 //
64 // Writes an object as the current property; the returned property
65 // writer will be subjected to a sequence of property writes and then
66 // discarded before any other properties are written to the "outer"
67 // property writer (which need not be the same type). The sub-writer
68 // will be used as if with the following code:
69 //
70 // {
71 // auto &&widget = W.find("widget").writeObject();
72 // widget.find("kind").writeWidgetKind(...);
73 // widget.find("declaration").writeDeclRef(...);
74 // }
75 
76 // WriteDispatcher is a template which does type-based forwarding to one
77 // of the write methods of the BasicWriter passed in:
78 //
79 // template <class ValueType>
80 // struct WriteDispatcher {
81 // template <class BasicWriter>
82 // static void write(BasicWriter &W, ValueType value);
83 // };
84 
85 // BasicWriterBase provides convenience implementations of the write
86 // methods for EnumPropertyType and SubclassPropertyType types that just
87 // defer to the "underlying" implementations (for UInt32 and the base class,
88 // respectively).
89 //
90 // template <class Impl>
91 // class BasicWriterBase {
92 // protected:
93 // Impl &asImpl();
94 // public:
95 // ...
96 // };
97 
98 // The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
99 #include "clang/AST/AbstractBasicWriter.inc"
100 
101 /// DataStreamBasicWriter provides convenience implementations for many
102 /// BasicWriter methods based on the assumption that the
103 /// ultimate writer implementation is based on a variable-length stream
104 /// of unstructured data (like Clang's module files). It is designed
105 /// to pair with DataStreamBasicReader.
106 ///
107 /// This class can also act as a PropertyWriter, implementing find("...")
108 /// by simply forwarding to itself.
109 ///
110 /// Unimplemented methods:
111 /// writeBool
112 /// writeUInt32
113 /// writeUInt64
114 /// writeIdentifier
115 /// writeSelector
116 /// writeSourceLocation
117 /// writeQualType
118 /// writeStmtRef
119 /// writeDeclRef
120 template <class Impl>
121 class DataStreamBasicWriter : public BasicWriterBase<Impl> {
122 protected:
123  using BasicWriterBase<Impl>::asImpl;
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>
143  asImpl().writeUInt32(array.size());
144  for (const T &elt : array) {
145  WriteDispatcher<T>::write(asImpl(), elt);
146  }
147  }
148 
149  template <class T>
151  WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value));
152  }
153 
154  void writeAPSInt(const llvm::APSInt &value) {
155  asImpl().writeBool(value.isUnsigned());
156  asImpl().writeAPInt(value);
157  }
158 
159  void writeAPInt(const llvm::APInt &value) {
160  asImpl().writeUInt32(value.getBitWidth());
161  const uint64_t *words = value.getRawData();
162  for (size_t i = 0, e = value.getNumWords(); i != e; ++i)
163  asImpl().writeUInt64(words[i]);
164  }
165 
167  static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t),
168  "update this if the value size changes");
169  asImpl().writeUInt32(value.getAsOpaqueValue());
170  }
171 
174  asImpl().writeUInt32(uint32_t(esi.Type));
175  if (esi.Type == EST_Dynamic) {
176  asImpl().writeArray(esi.Exceptions);
177  } else if (isComputedNoexcept(esi.Type)) {
178  asImpl().writeExprRef(esi.NoexceptExpr);
179  } else if (esi.Type == EST_Uninstantiated) {
180  asImpl().writeDeclRef(esi.SourceDecl);
181  asImpl().writeDeclRef(esi.SourceTemplate);
182  } else if (esi.Type == EST_Unevaluated) {
183  asImpl().writeDeclRef(esi.SourceDecl);
184  }
185  }
186 
188  static_assert(sizeof(epi.getOpaqueValue()) <= sizeof(uint32_t),
189  "opaque value doesn't fit into uint32_t");
190  asImpl().writeUInt32(epi.getOpaqueValue());
191  }
192 
194  // Nested name specifiers usually aren't too long. I think that 8 would
195  // typically accommodate the vast majority.
197 
198  // Push each of the NNS's onto a stack for serialization in reverse order.
199  while (NNS) {
200  nestedNames.push_back(NNS);
201  NNS = NNS->getPrefix();
202  }
203 
204  asImpl().writeUInt32(nestedNames.size());
205  while (!nestedNames.empty()) {
206  NNS = nestedNames.pop_back_val();
208  asImpl().writeNestedNameSpecifierKind(kind);
209  switch (kind) {
211  asImpl().writeIdentifier(NNS->getAsIdentifier());
212  continue;
213 
215  asImpl().writeNamespaceDeclRef(NNS->getAsNamespace());
216  continue;
217 
219  asImpl().writeNamespaceAliasDeclRef(NNS->getAsNamespaceAlias());
220  continue;
221 
224  asImpl().writeQualType(QualType(NNS->getAsType(), 0));
225  continue;
226 
228  // Don't need to write an associated value.
229  continue;
230 
232  asImpl().writeDeclRef(NNS->getAsRecordDecl());
233  continue;
234  }
235  llvm_unreachable("bad nested name specifier kind");
236  }
237  }
238 };
239 
240 } // end namespace serialization
241 } // end namespace clang
242 
243 #endif
A (possibly-)qualified type.
Definition: Type.h:655
Microsoft&#39;s &#39;__super&#39; specifier, stored as a CXXRecordDecl* of the class it appeared in...
NestedNameSpecifier * getPrefix() const
Return the prefix of this nested name specifier.
Defines the C++ template declaration subclasses.
void writeOptional(llvm::Optional< T > value)
An identifier, stored as an IdentifierInfo*.
llvm::Optional< T > makeOptionalFromNullable(const T &value)
A namespace, stored as a NamespaceDecl*.
SpecifierKind getKind() const
Determine what kind of nested name specifier is stored.
The collection of all-type qualifiers we support.
Definition: Type.h:144
const Type * getAsType() const
Retrieve the type stored in this nested name specifier.
unsigned char getOpaqueValue() const
Definition: Type.h:3622
CXXRecordDecl * getAsRecordDecl() const
Retrieve the record declaration stored in this nested name specifier.
IdentifierInfo * getAsIdentifier() const
Retrieve the identifier stored in this nested name specifier.
NamespaceAliasDecl * getAsNamespaceAlias() const
Retrieve the namespace alias stored in this nested name specifier.
FunctionDecl * SourceDecl
The function whose exception specification this is, for EST_Unevaluated and EST_Uninstantiated.
Definition: Type.h:3955
void writeAPSInt(const llvm::APSInt &value)
NamespaceDecl * getAsNamespace() const
Retrieve the namespace stored in this nested name specifier.
unsigned getAsOpaqueValue() const
Definition: Type.h:257
A namespace alias, stored as a NamespaceAliasDecl*.
void writeExtParameterInfo(FunctionProtoType::ExtParameterInfo epi)
SpecifierKind
The kind of specifier that completes this nested name specifier.
bool isComputedNoexcept(ExceptionSpecificationType ESpecType)
ExceptionSpecificationType Type
The kind of exception specification this is.
Definition: Type.h:3945
DataStreamBasicWriter provides convenience implementations for many BasicWriter methods based on the ...
llvm::APSInt APSInt
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
llvm::APInt APInt
Definition: Integral.h:27
Dataflow Directional Tag Classes.
not evaluated yet, for special member function
Interesting information about a specific parameter that can&#39;t simply be reflected in parameter&#39;s type...
Definition: Type.h:3573
A type that was preceded by the &#39;template&#39; keyword, stored as a Type*.
llvm::Optional< T * > makeOptionalFromPointer(T *value)
FunctionDecl * SourceTemplate
The function template whose exception specification this is instantiated from, for EST_Uninstantiated...
Definition: Type.h:3959
Holds information about the various types of exception specification.
Definition: Type.h:3943
ArrayRef< QualType > Exceptions
Explicitly-specified list of exception types.
Definition: Type.h:3948
Expr * NoexceptExpr
Noexcept expression, if this is a computed noexcept specification.
Definition: Type.h:3951
Impl & find(const char *propertyName)
Implement property-find by ignoring it.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Definition: DiagnosticIDs.h:60
void writeExceptionSpecInfo(const FunctionProtoType::ExceptionSpecInfo &esi)
void writeNestedNameSpecifier(NestedNameSpecifier *NNS)
The global specifier &#39;::&#39;. There is no stored value.
void writeArray(llvm::ArrayRef< T > array)