Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//==--- AbstractBasiceReader.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>
19
inline T makeNullableFromOptional(const std::optional<T> &value) {
20
  return (value ? *value : T());
21
}
22
 
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;
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.
133
  Impl &find(const char *propertyName) {
134
    return asImpl();
135
  }
136
 
137
  template <class T>
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.
144
  Impl &readObject() { return asImpl(); }
145
 
146
  template <class T>
147
  llvm::ArrayRef<T> readArray(llvm::SmallVectorImpl<T> &buffer) {
148
    assert(buffer.empty());
149
 
150
    uint32_t size = asImpl().readUInt32();
151
    buffer.reserve(size);
152
 
153
    for (uint32_t i = 0; i != size; ++i) {
154
      buffer.push_back(ReadDispatcher<T>::read(asImpl()));
155
    }
156
    return buffer;
157
  }
158
 
159
  template <class T, class... Args>
160
  std::optional<T> readOptional(Args &&...args) {
161
    return UnpackOptionalValue<T>::unpack(
162
             ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
163
  }
164
 
165
  llvm::APSInt readAPSInt() {
166
    bool isUnsigned = asImpl().readBool();
167
    llvm::APInt value = asImpl().readAPInt();
168
    return llvm::APSInt(std::move(value), isUnsigned);
169
  }
170
 
171
  llvm::APInt readAPInt() {
172
    unsigned bitWidth = asImpl().readUInt32();
173
    unsigned numWords = llvm::APInt::getNumWords(bitWidth);
174
    llvm::SmallVector<uint64_t, 4> data;
175
    for (uint32_t i = 0; i != numWords; ++i)
176
      data.push_back(asImpl().readUInt64());
177
    return llvm::APInt(bitWidth, numWords, &data[0]);
178
  }
179
 
180
  llvm::FixedPointSemantics readFixedPointSemantics() {
181
    unsigned width = asImpl().readUInt32();
182
    unsigned scale = asImpl().readUInt32();
183
    unsigned tmp = asImpl().readUInt32();
184
    bool isSigned = tmp & 0x1;
185
    bool isSaturated = tmp & 0x2;
186
    bool hasUnsignedPadding = tmp & 0x4;
187
    return llvm::FixedPointSemantics(width, scale, isSigned, isSaturated,
188
                                     hasUnsignedPadding);
189
  }
190
 
191
  APValue::LValuePathSerializationHelper readLValuePathSerializationHelper(
192
      SmallVectorImpl<APValue::LValuePathEntry> &path) {
193
    auto origTy = asImpl().readQualType();
194
    auto elemTy = origTy;
195
    unsigned pathLength = asImpl().readUInt32();
196
    for (unsigned i = 0; i < pathLength; ++i) {
197
      if (elemTy->template getAs<RecordType>()) {
198
        unsigned int_ = asImpl().readUInt32();
199
        Decl *decl = asImpl().template readDeclAs<Decl>();
200
        if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))
201
          elemTy = getASTContext().getRecordType(recordDecl);
202
        else
203
          elemTy = cast<ValueDecl>(decl)->getType();
204
        path.push_back(
205
            APValue::LValuePathEntry(APValue::BaseOrMemberType(decl, int_)));
206
      } else {
207
        elemTy = getASTContext().getAsArrayType(elemTy)->getElementType();
208
        path.push_back(
209
            APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()));
210
      }
211
    }
212
    return APValue::LValuePathSerializationHelper(path, origTy);
213
  }
214
 
215
  Qualifiers readQualifiers() {
216
    static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),
217
                  "update this if the value size changes");
218
    uint32_t value = asImpl().readUInt32();
219
    return Qualifiers::fromOpaqueValue(value);
220
  }
221
 
222
  FunctionProtoType::ExceptionSpecInfo
223
  readExceptionSpecInfo(llvm::SmallVectorImpl<QualType> &buffer) {
224
    FunctionProtoType::ExceptionSpecInfo esi;
225
    esi.Type = ExceptionSpecificationType(asImpl().readUInt32());
226
    if (esi.Type == EST_Dynamic) {
227
      esi.Exceptions = asImpl().template readArray<QualType>(buffer);
228
    } else if (isComputedNoexcept(esi.Type)) {
229
      esi.NoexceptExpr = asImpl().readExprRef();
230
    } else if (esi.Type == EST_Uninstantiated) {
231
      esi.SourceDecl = asImpl().readFunctionDeclRef();
232
      esi.SourceTemplate = asImpl().readFunctionDeclRef();
233
    } else if (esi.Type == EST_Unevaluated) {
234
      esi.SourceDecl = asImpl().readFunctionDeclRef();
235
    }
236
    return esi;
237
  }
238
 
239
  FunctionProtoType::ExtParameterInfo readExtParameterInfo() {
240
    static_assert(sizeof(FunctionProtoType::ExtParameterInfo().getOpaqueValue())
241
                    <= sizeof(uint32_t),
242
                  "opaque value doesn't fit into uint32_t");
243
    uint32_t value = asImpl().readUInt32();
244
    return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value);
245
  }
246
 
247
  NestedNameSpecifier *readNestedNameSpecifier() {
248
    auto &ctx = getASTContext();
249
 
250
    // We build this up iteratively.
251
    NestedNameSpecifier *cur = nullptr;
252
 
253
    uint32_t depth = asImpl().readUInt32();
254
    for (uint32_t i = 0; i != depth; ++i) {
255
      auto kind = asImpl().readNestedNameSpecifierKind();
256
      switch (kind) {
257
      case NestedNameSpecifier::Identifier:
258
        cur = NestedNameSpecifier::Create(ctx, cur,
259
                                          asImpl().readIdentifier());
260
        continue;
261
 
262
      case NestedNameSpecifier::Namespace:
263
        cur = NestedNameSpecifier::Create(ctx, cur,
264
                                          asImpl().readNamespaceDeclRef());
265
        continue;
266
 
267
      case NestedNameSpecifier::NamespaceAlias:
268
        cur = NestedNameSpecifier::Create(ctx, cur,
269
                                     asImpl().readNamespaceAliasDeclRef());
270
        continue;
271
 
272
      case NestedNameSpecifier::TypeSpec:
273
      case NestedNameSpecifier::TypeSpecWithTemplate:
274
        cur = NestedNameSpecifier::Create(ctx, cur,
275
                          kind == NestedNameSpecifier::TypeSpecWithTemplate,
276
                          asImpl().readQualType().getTypePtr());
277
        continue;
278
 
279
      case NestedNameSpecifier::Global:
280
        cur = NestedNameSpecifier::GlobalSpecifier(ctx);
281
        continue;
282
 
283
      case NestedNameSpecifier::Super:
284
        cur = NestedNameSpecifier::SuperSpecifier(ctx,
285
                                            asImpl().readCXXRecordDeclRef());
286
        continue;
287
      }
288
      llvm_unreachable("bad nested name specifier kind");
289
    }
290
 
291
    return cur;
292
  }
293
};
294
 
295
} // end namespace serialization
296
} // end namespace clang
297
 
298
#endif