forked from OSchip/llvm-project
Abstract serialization: TableGen the (de)serialization code for Types.
The basic technical design here is that we have three levels of readers and writers: - At the lowest level, there's a `Basic{Reader,Writer}` that knows how to emit the basic structures of the AST. CRTP allows this to be metaprogrammed so that the client only needs to support a handful of primitive types (e.g. `uint64_t` and `IdentifierInfo*`) and more complicated "inline" structures such as `DeclarationName` can just be emitted in terms of those primitives. In Clang's binary-serialization code, these are `ASTRecord{Reader,Writer}`. For now, a large number of basic structures are still emitted explicitly by code on those classes rather than by either TableGen or CRTP metaprogramming, but I expect to move more of these over. - In the middle, there's a `Property{Reader,Writer}` which is responsible for processing the properties of a larger object. The object-level reader/writer asks the property-level reader/writer to project out a particular property, yielding a basic reader/writer which will be used to read/write the property's value, like so: ``` propertyWriter.find("count").writeUInt32(node->getCount()); ``` Clang's binary-serialization code ignores this level (it uses the basic reader/writer as the property reader/writer and has the projection methods just return `*this`) and simply relies on the roperties being read/written in a stable order. - At the highest level, there's an object reader/writer (e.g. `Type{Reader,Writer}` which emits a logical object with properties. Think of this as writing something like a JSON dictionary literal. I haven't introduced support for bitcode abbreviations yet --- it turns out that there aren't any operative abbreviations for types besides the QualType one --- but I do have some ideas of how they should work. At any rate, they'll be necessary in order to handle statements. I'm sorry for not disentangling the patches that added basic and type reader/writers; I made some effort to, but I ran out of energy after disentangling a number of other patches from the work. Negligible impact on module size, time to build a set of about 20 fairly large modules, or time to read a few declarations out of them.
This commit is contained in:
parent
6404bd2362
commit
d505e57cc2
|
@ -145,6 +145,10 @@ class Context;
|
|||
|
||||
} // namespace interp
|
||||
|
||||
namespace serialization {
|
||||
template <class> class AbstractTypeReader;
|
||||
} // namespace serialization
|
||||
|
||||
struct TypeInfo {
|
||||
uint64_t Width = 0;
|
||||
unsigned Align = 0;
|
||||
|
@ -413,6 +417,7 @@ private:
|
|||
friend class ASTDeclReader;
|
||||
friend class ASTReader;
|
||||
friend class ASTWriter;
|
||||
template <class> friend class serialization::AbstractTypeReader;
|
||||
friend class CXXRecordDecl;
|
||||
|
||||
/// A mapping to contain the template or declaration that
|
||||
|
|
|
@ -0,0 +1,368 @@
|
|||
//==--- AbstractBasiceReader.h - Abstract basic value deserialization -----===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CLANG_AST_ABSTRACTBASICREADER_H
|
||||
#define CLANG_AST_ABSTRACTBASICREADER_H
|
||||
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
|
||||
namespace clang {
|
||||
namespace serialization {
|
||||
|
||||
template <class T>
|
||||
inline T makeNullableFromOptional(const Optional<T> &value) {
|
||||
return (value ? *value : T());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T *makePointerFromOptional(Optional<T *> value) {
|
||||
return (value ? *value : nullptr);
|
||||
}
|
||||
|
||||
// PropertyReader is a class concept that requires the following method:
|
||||
// BasicReader find(llvm::StringRef propertyName);
|
||||
// where BasicReader is some class conforming to the BasicReader concept.
|
||||
// An abstract AST-node reader is created with a PropertyReader and
|
||||
// performs a sequence of calls like so:
|
||||
// propertyReader.find(propertyName).read##TypeName()
|
||||
// to read the properties of the node it is deserializing.
|
||||
|
||||
// BasicReader is a class concept that requires methods like:
|
||||
// ValueType read##TypeName();
|
||||
// where TypeName is the name of a PropertyType node from PropertiesBase.td
|
||||
// and ValueType is the corresponding C++ type name. The read method may
|
||||
// require one or more buffer arguments.
|
||||
|
||||
// ReadDispatcher does type-based forwarding to one of the read methods
|
||||
// on the BasicReader passed in:
|
||||
//
|
||||
// template <class ValueType>
|
||||
// struct ReadDispatcher {
|
||||
// template <class BasicReader, class... BufferTypes>
|
||||
// static ValueType read(BasicReader &R, BufferTypes &&...);
|
||||
// };
|
||||
|
||||
// BasicReaderBase provides convenience implementations of the read methods
|
||||
// for EnumPropertyType and SubclassPropertyType types that just defer to
|
||||
// the "underlying" implementations (for UInt32 and the base class,
|
||||
// respectively).
|
||||
//
|
||||
// template <class Impl>
|
||||
// class BasicReaderBase {
|
||||
// protected:
|
||||
// BasicReaderBase(ASTContext &ctx);
|
||||
// Impl &asImpl();
|
||||
// public:
|
||||
// ASTContext &getASTContext();
|
||||
// ...
|
||||
// };
|
||||
|
||||
// The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
|
||||
#include "clang/AST/AbstractBasicReader.inc"
|
||||
|
||||
/// DataStreamBasicReader provides convenience implementations for many
|
||||
/// BasicReader methods based on the assumption that the
|
||||
/// ultimate reader implementation is based on a variable-length stream
|
||||
/// of unstructured data (like Clang's module files). It is designed
|
||||
/// to pair with DataStreamBasicWriter.
|
||||
///
|
||||
/// This class can also act as a PropertyReader, implementing find("...")
|
||||
/// by simply forwarding to itself.
|
||||
///
|
||||
/// Unimplemented methods:
|
||||
/// readBool
|
||||
/// readUInt32
|
||||
/// readUInt64
|
||||
/// readIdentifier
|
||||
/// readSelector
|
||||
/// readSourceLocation
|
||||
/// readQualType
|
||||
/// readStmtRef
|
||||
/// readDeclRef
|
||||
template <class Impl>
|
||||
class DataStreamBasicReader : public BasicReaderBase<Impl> {
|
||||
protected:
|
||||
using BasicReaderBase<Impl>::asImpl;
|
||||
DataStreamBasicReader(ASTContext &ctx) : BasicReaderBase<Impl>(ctx) {}
|
||||
|
||||
public:
|
||||
using BasicReaderBase<Impl>::getASTContext;
|
||||
|
||||
/// Implement property-find by ignoring it. We rely on properties being
|
||||
/// serialized and deserialized in a reliable order instead.
|
||||
Impl &find(const char *propertyName) {
|
||||
return asImpl();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
llvm::ArrayRef<T> readArray(llvm::SmallVectorImpl<T> &buffer) {
|
||||
assert(buffer.empty());
|
||||
|
||||
uint32_t size = asImpl().readUInt32();
|
||||
buffer.reserve(size);
|
||||
|
||||
for (uint32_t i = 0; i != size; ++i) {
|
||||
buffer.push_back(ReadDispatcher<T>::read(asImpl()));
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
llvm::Optional<T> readOptional(Args &&...args) {
|
||||
return UnpackOptionalValue<T>::unpack(
|
||||
ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
llvm::APSInt readAPSInt() {
|
||||
bool isUnsigned = asImpl().readBool();
|
||||
llvm::APInt value = asImpl().readAPInt();
|
||||
return llvm::APSInt(std::move(value), isUnsigned);
|
||||
}
|
||||
|
||||
llvm::APInt readAPInt() {
|
||||
unsigned bitWidth = asImpl().readUInt32();
|
||||
unsigned numWords = llvm::APInt::getNumWords(bitWidth);
|
||||
llvm::SmallVector<uint64_t, 4> data;
|
||||
for (uint32_t i = 0; i != numWords; ++i)
|
||||
data.push_back(asImpl().readUInt64());
|
||||
return llvm::APInt(bitWidth, numWords, &data[0]);
|
||||
}
|
||||
|
||||
Qualifiers readQualifiers() {
|
||||
static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),
|
||||
"update this if the value size changes");
|
||||
uint32_t value = asImpl().readUInt32();
|
||||
return Qualifiers::fromOpaqueValue(value);
|
||||
}
|
||||
|
||||
FunctionProtoType::ExceptionSpecInfo
|
||||
readExceptionSpecInfo(llvm::SmallVectorImpl<QualType> &buffer) {
|
||||
FunctionProtoType::ExceptionSpecInfo esi;
|
||||
esi.Type = ExceptionSpecificationType(asImpl().readUInt32());
|
||||
if (esi.Type == EST_Dynamic) {
|
||||
esi.Exceptions = asImpl().template readArray<QualType>(buffer);
|
||||
} else if (isComputedNoexcept(esi.Type)) {
|
||||
esi.NoexceptExpr = asImpl().readExprRef();
|
||||
} else if (esi.Type == EST_Uninstantiated) {
|
||||
esi.SourceDecl = asImpl().readFunctionDeclRef();
|
||||
esi.SourceTemplate = asImpl().readFunctionDeclRef();
|
||||
} else if (esi.Type == EST_Unevaluated) {
|
||||
esi.SourceDecl = asImpl().readFunctionDeclRef();
|
||||
}
|
||||
return esi;
|
||||
}
|
||||
|
||||
FunctionProtoType::ExtParameterInfo readExtParameterInfo() {
|
||||
static_assert(sizeof(FunctionProtoType::ExtParameterInfo().getOpaqueValue())
|
||||
<= sizeof(uint32_t),
|
||||
"opaque value doesn't fit into uint32_t");
|
||||
uint32_t value = asImpl().readUInt32();
|
||||
return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value);
|
||||
}
|
||||
|
||||
DeclarationName readDeclarationName() {
|
||||
auto &ctx = getASTContext();
|
||||
auto kind = asImpl().readDeclarationNameKind();
|
||||
switch (kind) {
|
||||
case DeclarationName::Identifier:
|
||||
return DeclarationName(asImpl().readIdentifier());
|
||||
|
||||
case DeclarationName::ObjCZeroArgSelector:
|
||||
case DeclarationName::ObjCOneArgSelector:
|
||||
case DeclarationName::ObjCMultiArgSelector:
|
||||
return DeclarationName(asImpl().readSelector());
|
||||
|
||||
case DeclarationName::CXXConstructorName:
|
||||
return ctx.DeclarationNames.getCXXConstructorName(
|
||||
ctx.getCanonicalType(asImpl().readQualType()));
|
||||
|
||||
case DeclarationName::CXXDestructorName:
|
||||
return ctx.DeclarationNames.getCXXDestructorName(
|
||||
ctx.getCanonicalType(asImpl().readQualType()));
|
||||
|
||||
case DeclarationName::CXXConversionFunctionName:
|
||||
return ctx.DeclarationNames.getCXXConversionFunctionName(
|
||||
ctx.getCanonicalType(asImpl().readQualType()));
|
||||
|
||||
case DeclarationName::CXXDeductionGuideName:
|
||||
return ctx.DeclarationNames.getCXXDeductionGuideName(
|
||||
asImpl().readTemplateDeclRef());
|
||||
|
||||
case DeclarationName::CXXOperatorName:
|
||||
return ctx.DeclarationNames.getCXXOperatorName(
|
||||
asImpl().readOverloadedOperatorKind());
|
||||
|
||||
case DeclarationName::CXXLiteralOperatorName:
|
||||
return ctx.DeclarationNames.getCXXLiteralOperatorName(
|
||||
asImpl().readIdentifier());
|
||||
|
||||
case DeclarationName::CXXUsingDirective:
|
||||
return DeclarationName::getUsingDirectiveName();
|
||||
}
|
||||
llvm_unreachable("bad name kind");
|
||||
}
|
||||
|
||||
TemplateName readTemplateName() {
|
||||
auto &ctx = getASTContext();
|
||||
auto kind = asImpl().readTemplateNameKind();
|
||||
switch (kind) {
|
||||
case TemplateName::Template:
|
||||
return TemplateName(asImpl().readTemplateDeclRef());
|
||||
|
||||
case TemplateName::OverloadedTemplate: {
|
||||
SmallVector<NamedDecl *, 8> buffer;
|
||||
auto overloadsArray = asImpl().template readArray<NamedDecl*>(buffer);
|
||||
|
||||
// Copy into an UnresolvedSet to satisfy the interface.
|
||||
UnresolvedSet<8> overloads;
|
||||
for (auto overload : overloadsArray) {
|
||||
overloads.addDecl(overload);
|
||||
}
|
||||
|
||||
return ctx.getOverloadedTemplateName(overloads.begin(), overloads.end());
|
||||
}
|
||||
|
||||
case TemplateName::AssumedTemplate: {
|
||||
auto name = asImpl().readDeclarationName();
|
||||
return ctx.getAssumedTemplateName(name);
|
||||
}
|
||||
|
||||
case TemplateName::QualifiedTemplate: {
|
||||
auto qual = asImpl().readNestedNameSpecifier();
|
||||
auto hasTemplateKeyword = asImpl().readBool();
|
||||
auto templateDecl = asImpl().readTemplateDeclRef();
|
||||
return ctx.getQualifiedTemplateName(qual, hasTemplateKeyword,
|
||||
templateDecl);
|
||||
}
|
||||
|
||||
case TemplateName::DependentTemplate: {
|
||||
auto qual = asImpl().readNestedNameSpecifier();
|
||||
auto isIdentifier = asImpl().readBool();
|
||||
if (isIdentifier) {
|
||||
return ctx.getDependentTemplateName(qual, asImpl().readIdentifier());
|
||||
} else {
|
||||
return ctx.getDependentTemplateName(qual,
|
||||
asImpl().readOverloadedOperatorKind());
|
||||
}
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParm: {
|
||||
auto param = asImpl().readTemplateTemplateParmDeclRef();
|
||||
auto replacement = asImpl().readTemplateName();
|
||||
return ctx.getSubstTemplateTemplateParm(param, replacement);
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParmPack: {
|
||||
auto param = asImpl().readTemplateTemplateParmDeclRef();
|
||||
auto replacement = asImpl().readTemplateName();
|
||||
return ctx.getSubstTemplateTemplateParmPack(param, replacement);
|
||||
}
|
||||
}
|
||||
llvm_unreachable("bad template name kind");
|
||||
}
|
||||
|
||||
TemplateArgument readTemplateArgument(bool canonicalize = false) {
|
||||
if (canonicalize) {
|
||||
return getASTContext().getCanonicalTemplateArgument(
|
||||
readTemplateArgument(false));
|
||||
}
|
||||
|
||||
auto kind = asImpl().readTemplateArgumentKind();
|
||||
switch (kind) {
|
||||
case TemplateArgument::Null:
|
||||
return TemplateArgument();
|
||||
case TemplateArgument::Type:
|
||||
return TemplateArgument(asImpl().readQualType());
|
||||
case TemplateArgument::Declaration: {
|
||||
auto decl = asImpl().readValueDeclRef();
|
||||
auto type = asImpl().readQualType();
|
||||
return TemplateArgument(decl, type);
|
||||
}
|
||||
case TemplateArgument::NullPtr:
|
||||
return TemplateArgument(asImpl().readQualType(), /*nullptr*/ true);
|
||||
case TemplateArgument::Integral: {
|
||||
auto value = asImpl().readAPSInt();
|
||||
auto type = asImpl().readQualType();
|
||||
return TemplateArgument(getASTContext(), value, type);
|
||||
}
|
||||
case TemplateArgument::Template:
|
||||
return TemplateArgument(asImpl().readTemplateName());
|
||||
case TemplateArgument::TemplateExpansion: {
|
||||
auto name = asImpl().readTemplateName();
|
||||
auto numExpansions = asImpl().template readOptional<uint32_t>();
|
||||
return TemplateArgument(name, numExpansions);
|
||||
}
|
||||
case TemplateArgument::Expression:
|
||||
return TemplateArgument(asImpl().readExprRef());
|
||||
case TemplateArgument::Pack: {
|
||||
llvm::SmallVector<TemplateArgument, 8> packBuffer;
|
||||
auto pack = asImpl().template readArray<TemplateArgument>(packBuffer);
|
||||
|
||||
// Copy the pack into the ASTContext.
|
||||
TemplateArgument *contextPack =
|
||||
new (getASTContext()) TemplateArgument[pack.size()];
|
||||
for (size_t i = 0, e = pack.size(); i != e; ++i)
|
||||
contextPack[i] = pack[i];
|
||||
return TemplateArgument(llvm::makeArrayRef(contextPack, pack.size()));
|
||||
}
|
||||
}
|
||||
llvm_unreachable("bad template argument kind");
|
||||
}
|
||||
|
||||
NestedNameSpecifier *readNestedNameSpecifier() {
|
||||
auto &ctx = getASTContext();
|
||||
|
||||
// We build this up iteratively.
|
||||
NestedNameSpecifier *cur = nullptr;
|
||||
|
||||
uint32_t depth = asImpl().readUInt32();
|
||||
for (uint32_t i = 0; i != depth; ++i) {
|
||||
auto kind = asImpl().readNestedNameSpecifierKind();
|
||||
switch (kind) {
|
||||
case NestedNameSpecifier::Identifier:
|
||||
cur = NestedNameSpecifier::Create(ctx, cur,
|
||||
asImpl().readIdentifier());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Namespace:
|
||||
cur = NestedNameSpecifier::Create(ctx, cur,
|
||||
asImpl().readNamespaceDeclRef());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::NamespaceAlias:
|
||||
cur = NestedNameSpecifier::Create(ctx, cur,
|
||||
asImpl().readNamespaceAliasDeclRef());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
cur = NestedNameSpecifier::Create(ctx, cur,
|
||||
kind == NestedNameSpecifier::TypeSpecWithTemplate,
|
||||
asImpl().readQualType().getTypePtr());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Global:
|
||||
cur = NestedNameSpecifier::GlobalSpecifier(ctx);
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Super:
|
||||
cur = NestedNameSpecifier::SuperSpecifier(ctx,
|
||||
asImpl().readCXXRecordDeclRef());
|
||||
continue;
|
||||
}
|
||||
llvm_unreachable("bad nested name specifier kind");
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace serialization
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
|
@ -0,0 +1,335 @@
|
|||
//==--- AbstractBasicWriter.h - Abstract basic value serialization --------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CLANG_AST_ABSTRACTBASICWRITER_H
|
||||
#define CLANG_AST_ABSTRACTBASICWRITER_H
|
||||
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
|
||||
namespace clang {
|
||||
namespace serialization {
|
||||
|
||||
template <class T>
|
||||
inline llvm::Optional<T> makeOptionalFromNullable(const T &value) {
|
||||
return (value.isNull()
|
||||
? llvm::Optional<T>()
|
||||
: llvm::Optional<T>(value));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline llvm::Optional<T*> makeOptionalFromPointer(T *value) {
|
||||
return (value ? llvm::Optional<T*>(value) : llvm::Optional<T*>());
|
||||
}
|
||||
|
||||
// PropertyWriter is a class concept that requires the following method:
|
||||
// BasicWriter find(llvm::StringRef propertyName);
|
||||
// where BasicWriter is some class conforming to the BasicWriter concept.
|
||||
// An abstract AST-node writer is created with a PropertyWriter and
|
||||
// performs a sequence of calls like so:
|
||||
// propertyWriter.find(propertyName).write##TypeName(value)
|
||||
// to write the properties of the node it is serializing.
|
||||
|
||||
// BasicWriter is a class concept that requires methods like:
|
||||
// void write##TypeName(ValueType value);
|
||||
// where TypeName is the name of a PropertyType node from PropertiesBase.td
|
||||
// and ValueType is the corresponding C++ type name.
|
||||
|
||||
// WriteDispatcher is a template which does type-based forwarding to one
|
||||
// of the write methods of the BasicWriter passed in:
|
||||
//
|
||||
// template <class ValueType>
|
||||
// struct WriteDispatcher {
|
||||
// template <class BasicWriter>
|
||||
// static void write(BasicWriter &W, ValueType value);
|
||||
// };
|
||||
|
||||
// BasicWriterBase provides convenience implementations of the write
|
||||
// methods for EnumPropertyType and SubclassPropertyType types that just
|
||||
// defer to the "underlying" implementations (for UInt32 and the base class,
|
||||
// respectively).
|
||||
//
|
||||
// template <class Impl>
|
||||
// class BasicWriterBase {
|
||||
// protected:
|
||||
// Impl &asImpl();
|
||||
// public:
|
||||
// ...
|
||||
// };
|
||||
|
||||
// The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
|
||||
#include "clang/AST/AbstractBasicWriter.inc"
|
||||
|
||||
/// DataStreamBasicWriter provides convenience implementations for many
|
||||
/// BasicWriter methods based on the assumption that the
|
||||
/// ultimate writer implementation is based on a variable-length stream
|
||||
/// of unstructured data (like Clang's module files). It is designed
|
||||
/// to pair with DataStreamBasicReader.
|
||||
///
|
||||
/// This class can also act as a PropertyWriter, implementing find("...")
|
||||
/// by simply forwarding to itself.
|
||||
///
|
||||
/// Unimplemented methods:
|
||||
/// writeBool
|
||||
/// writeUInt32
|
||||
/// writeUInt64
|
||||
/// writeIdentifier
|
||||
/// writeSelector
|
||||
/// writeSourceLocation
|
||||
/// writeQualType
|
||||
/// writeStmtRef
|
||||
/// writeDeclRef
|
||||
template <class Impl>
|
||||
class DataStreamBasicWriter : public BasicWriterBase<Impl> {
|
||||
protected:
|
||||
using BasicWriterBase<Impl>::asImpl;
|
||||
|
||||
public:
|
||||
/// Implement property-find by ignoring it. We rely on properties being
|
||||
/// serialized and deserialized in a reliable order instead.
|
||||
Impl &find(const char *propertyName) {
|
||||
return asImpl();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void writeArray(llvm::ArrayRef<T> array) {
|
||||
asImpl().writeUInt32(array.size());
|
||||
for (const T &elt : array) {
|
||||
WriteDispatcher<T>::write(asImpl(), elt);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void writeOptional(llvm::Optional<T> value) {
|
||||
WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value));
|
||||
}
|
||||
|
||||
void writeAPSInt(const llvm::APSInt &value) {
|
||||
asImpl().writeBool(value.isUnsigned());
|
||||
asImpl().writeAPInt(value);
|
||||
}
|
||||
|
||||
void writeAPInt(const llvm::APInt &value) {
|
||||
asImpl().writeUInt32(value.getBitWidth());
|
||||
const uint64_t *words = value.getRawData();
|
||||
for (size_t i = 0, e = value.getNumWords(); i != e; ++i)
|
||||
asImpl().writeUInt64(words[i]);
|
||||
}
|
||||
|
||||
void writeQualifiers(Qualifiers value) {
|
||||
static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t),
|
||||
"update this if the value size changes");
|
||||
asImpl().writeUInt32(value.getAsOpaqueValue());
|
||||
}
|
||||
|
||||
void writeExceptionSpecInfo(
|
||||
const FunctionProtoType::ExceptionSpecInfo &esi) {
|
||||
asImpl().writeUInt32(uint32_t(esi.Type));
|
||||
if (esi.Type == EST_Dynamic) {
|
||||
asImpl().writeArray(esi.Exceptions);
|
||||
} else if (isComputedNoexcept(esi.Type)) {
|
||||
asImpl().writeExprRef(esi.NoexceptExpr);
|
||||
} else if (esi.Type == EST_Uninstantiated) {
|
||||
asImpl().writeDeclRef(esi.SourceDecl);
|
||||
asImpl().writeDeclRef(esi.SourceTemplate);
|
||||
} else if (esi.Type == EST_Unevaluated) {
|
||||
asImpl().writeDeclRef(esi.SourceDecl);
|
||||
}
|
||||
}
|
||||
|
||||
void writeExtParameterInfo(FunctionProtoType::ExtParameterInfo epi) {
|
||||
static_assert(sizeof(epi.getOpaqueValue()) <= sizeof(uint32_t),
|
||||
"opaque value doesn't fit into uint32_t");
|
||||
asImpl().writeUInt32(epi.getOpaqueValue());
|
||||
}
|
||||
|
||||
void writeDeclarationName(DeclarationName name) {
|
||||
asImpl().writeDeclarationNameKind(name.getNameKind());
|
||||
switch (name.getNameKind()) {
|
||||
case DeclarationName::Identifier:
|
||||
asImpl().writeIdentifier(name.getAsIdentifierInfo());
|
||||
return;
|
||||
|
||||
case DeclarationName::ObjCZeroArgSelector:
|
||||
case DeclarationName::ObjCOneArgSelector:
|
||||
case DeclarationName::ObjCMultiArgSelector:
|
||||
asImpl().writeSelector(name.getObjCSelector());
|
||||
return;
|
||||
|
||||
case DeclarationName::CXXConstructorName:
|
||||
case DeclarationName::CXXDestructorName:
|
||||
case DeclarationName::CXXConversionFunctionName:
|
||||
asImpl().writeQualType(name.getCXXNameType());
|
||||
return;
|
||||
|
||||
case DeclarationName::CXXDeductionGuideName:
|
||||
asImpl().writeDeclRef(name.getCXXDeductionGuideTemplate());
|
||||
return;
|
||||
|
||||
case DeclarationName::CXXOperatorName:
|
||||
asImpl().writeOverloadedOperatorKind(name.getCXXOverloadedOperator());
|
||||
return;
|
||||
|
||||
case DeclarationName::CXXLiteralOperatorName:
|
||||
asImpl().writeIdentifier(name.getCXXLiteralIdentifier());
|
||||
return;
|
||||
|
||||
case DeclarationName::CXXUsingDirective:
|
||||
// No extra data to emit
|
||||
return;
|
||||
}
|
||||
llvm_unreachable("bad name kind");
|
||||
}
|
||||
|
||||
void writeTemplateName(TemplateName name) {
|
||||
asImpl().writeTemplateNameKind(name.getKind());
|
||||
switch (name.getKind()) {
|
||||
case TemplateName::Template:
|
||||
asImpl().writeDeclRef(name.getAsTemplateDecl());
|
||||
return;
|
||||
|
||||
case TemplateName::OverloadedTemplate: {
|
||||
OverloadedTemplateStorage *overload = name.getAsOverloadedTemplate();
|
||||
asImpl().writeArray(llvm::makeArrayRef(overload->begin(),
|
||||
overload->end()));
|
||||
return;
|
||||
}
|
||||
|
||||
case TemplateName::AssumedTemplate: {
|
||||
AssumedTemplateStorage *assumed = name.getAsAssumedTemplateName();
|
||||
asImpl().writeDeclarationName(assumed->getDeclName());
|
||||
return;
|
||||
}
|
||||
|
||||
case TemplateName::QualifiedTemplate: {
|
||||
QualifiedTemplateName *qual = name.getAsQualifiedTemplateName();
|
||||
asImpl().writeNestedNameSpecifier(qual->getQualifier());
|
||||
asImpl().writeBool(qual->hasTemplateKeyword());
|
||||
asImpl().writeDeclRef(qual->getTemplateDecl());
|
||||
return;
|
||||
}
|
||||
|
||||
case TemplateName::DependentTemplate: {
|
||||
DependentTemplateName *dep = name.getAsDependentTemplateName();
|
||||
asImpl().writeNestedNameSpecifier(dep->getQualifier());
|
||||
asImpl().writeBool(dep->isIdentifier());
|
||||
if (dep->isIdentifier())
|
||||
asImpl().writeIdentifier(dep->getIdentifier());
|
||||
else
|
||||
asImpl().writeOverloadedOperatorKind(dep->getOperator());
|
||||
return;
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParm: {
|
||||
auto subst = name.getAsSubstTemplateTemplateParm();
|
||||
asImpl().writeDeclRef(subst->getParameter());
|
||||
asImpl().writeTemplateName(subst->getReplacement());
|
||||
return;
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParmPack: {
|
||||
auto substPack = name.getAsSubstTemplateTemplateParmPack();
|
||||
asImpl().writeDeclRef(substPack->getParameterPack());
|
||||
asImpl().writeTemplateArgument(substPack->getArgumentPack());
|
||||
return;
|
||||
}
|
||||
}
|
||||
llvm_unreachable("bad template name kind");
|
||||
}
|
||||
|
||||
void writeTemplateArgument(const TemplateArgument &arg) {
|
||||
asImpl().writeTemplateArgumentKind(arg.getKind());
|
||||
switch (arg.getKind()) {
|
||||
case TemplateArgument::Null:
|
||||
return;
|
||||
case TemplateArgument::Type:
|
||||
asImpl().writeQualType(arg.getAsType());
|
||||
return;
|
||||
case TemplateArgument::Declaration:
|
||||
asImpl().writeValueDeclRef(arg.getAsDecl());
|
||||
asImpl().writeQualType(arg.getParamTypeForDecl());
|
||||
return;
|
||||
case TemplateArgument::NullPtr:
|
||||
asImpl().writeQualType(arg.getNullPtrType());
|
||||
return;
|
||||
case TemplateArgument::Integral:
|
||||
asImpl().writeAPSInt(arg.getAsIntegral());
|
||||
asImpl().writeQualType(arg.getIntegralType());
|
||||
return;
|
||||
case TemplateArgument::Template:
|
||||
asImpl().writeTemplateName(arg.getAsTemplateOrTemplatePattern());
|
||||
return;
|
||||
case TemplateArgument::TemplateExpansion: {
|
||||
asImpl().writeTemplateName(arg.getAsTemplateOrTemplatePattern());
|
||||
// Convert Optional<unsigned> to Optional<uint32>, just in case.
|
||||
Optional<unsigned> numExpansions = arg.getNumTemplateExpansions();
|
||||
Optional<uint32_t> numExpansions32;
|
||||
if (numExpansions) numExpansions32 = *numExpansions;
|
||||
asImpl().template writeOptional<uint32_t>(numExpansions32);
|
||||
return;
|
||||
}
|
||||
case TemplateArgument::Expression:
|
||||
asImpl().writeExprRef(arg.getAsExpr());
|
||||
return;
|
||||
case TemplateArgument::Pack:
|
||||
asImpl().template writeArray<TemplateArgument>(arg.pack_elements());
|
||||
return;
|
||||
}
|
||||
llvm_unreachable("bad template argument kind");
|
||||
}
|
||||
|
||||
void writeNestedNameSpecifier(NestedNameSpecifier *NNS) {
|
||||
// Nested name specifiers usually aren't too long. I think that 8 would
|
||||
// typically accommodate the vast majority.
|
||||
SmallVector<NestedNameSpecifier *, 8> nestedNames;
|
||||
|
||||
// Push each of the NNS's onto a stack for serialization in reverse order.
|
||||
while (NNS) {
|
||||
nestedNames.push_back(NNS);
|
||||
NNS = NNS->getPrefix();
|
||||
}
|
||||
|
||||
asImpl().writeUInt32(nestedNames.size());
|
||||
while (!nestedNames.empty()) {
|
||||
NNS = nestedNames.pop_back_val();
|
||||
NestedNameSpecifier::SpecifierKind kind = NNS->getKind();
|
||||
asImpl().writeNestedNameSpecifierKind(kind);
|
||||
switch (kind) {
|
||||
case NestedNameSpecifier::Identifier:
|
||||
asImpl().writeIdentifier(NNS->getAsIdentifier());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Namespace:
|
||||
asImpl().writeNamespaceDeclRef(NNS->getAsNamespace());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::NamespaceAlias:
|
||||
asImpl().writeNamespaceAliasDeclRef(NNS->getAsNamespaceAlias());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
asImpl().writeQualType(QualType(NNS->getAsType(), 0));
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Global:
|
||||
// Don't need to write an associated value.
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Super:
|
||||
asImpl().writeDeclRef(NNS->getAsRecordDecl());
|
||||
continue;
|
||||
}
|
||||
llvm_unreachable("bad nested name specifier kind");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace serialization
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
//==--- AbstractTypeReader.h - Abstract deserialization for types ---------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CLANG_AST_ABSTRACTTYPEREADER_H
|
||||
#define CLANG_AST_ABSTRACTTYPEREADER_H
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/AbstractBasicReader.h"
|
||||
|
||||
namespace clang {
|
||||
namespace serialization {
|
||||
|
||||
// template <class PropertyReader>
|
||||
// class AbstractTypeReader {
|
||||
// public:
|
||||
// AbstractTypeReader(PropertyReader &W);
|
||||
// QualType read(Type::TypeClass kind);
|
||||
// };
|
||||
//
|
||||
// The actual class is auto-generated; see ClangASTPropertiesEmitter.cpp.
|
||||
#include "clang/AST/AbstractTypeReader.inc"
|
||||
|
||||
} // end namespace serialization
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
//==--- AbstractTypeWriter.h - Abstract serialization for types -----------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CLANG_AST_ABSTRACTTYPEWRITER_H
|
||||
#define CLANG_AST_ABSTRACTTYPEWRITER_H
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/AbstractBasicWriter.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
|
||||
namespace clang {
|
||||
namespace serialization {
|
||||
|
||||
// template <class PropertyWriter>
|
||||
// class AbstractTypeWriter {
|
||||
// public:
|
||||
// AbstractTypeWriter(PropertyWriter &W);
|
||||
// void write(QualType type);
|
||||
// };
|
||||
//
|
||||
// The actual class is auto-generated; see ClangASTPropertiesEmitter.cpp.
|
||||
#include "clang/AST/AbstractTypeWriter.inc"
|
||||
|
||||
} // end namespace serialization
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
|
@ -43,6 +43,14 @@ clang_tablegen(AbstractBasicWriter.inc -gen-clang-basic-writer
|
|||
SOURCE PropertiesBase.td
|
||||
TARGET ClangAbstractBasicWriter)
|
||||
|
||||
clang_tablegen(AbstractTypeReader.inc -gen-clang-type-reader
|
||||
SOURCE TypeProperties.td
|
||||
TARGET ClangAbstractTypeReader)
|
||||
|
||||
clang_tablegen(AbstractTypeWriter.inc -gen-clang-type-writer
|
||||
SOURCE TypeProperties.td
|
||||
TARGET ClangAbstractTypeWriter)
|
||||
|
||||
clang_tablegen(CommentNodes.inc -gen-clang-comment-nodes
|
||||
SOURCE ../Basic/CommentNodes.td
|
||||
TARGET ClangCommentNodes)
|
||||
|
|
|
@ -66,6 +66,11 @@ enum {
|
|||
TypeAlignment = 1 << TypeAlignmentInBits
|
||||
};
|
||||
|
||||
namespace serialization {
|
||||
template <class T> class AbstractTypeReader;
|
||||
template <class T> class AbstractTypeWriter;
|
||||
}
|
||||
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
|
@ -1847,6 +1852,8 @@ protected:
|
|||
public:
|
||||
friend class ASTReader;
|
||||
friend class ASTWriter;
|
||||
template <class T> friend class serialization::AbstractTypeReader;
|
||||
template <class T> friend class serialization::AbstractTypeWriter;
|
||||
|
||||
Type(const Type &) = delete;
|
||||
Type(Type &&) = delete;
|
||||
|
@ -4448,6 +4455,7 @@ public:
|
|||
|
||||
class TagType : public Type {
|
||||
friend class ASTReader;
|
||||
template <class T> friend class serialization::AbstractTypeReader;
|
||||
|
||||
/// Stores the TagDecl associated with this type. The decl may point to any
|
||||
/// TagDecl that declares the entity.
|
||||
|
@ -5085,6 +5093,7 @@ class InjectedClassNameType : public Type {
|
|||
friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not
|
||||
// currently suitable for AST reading, too much
|
||||
// interdependencies.
|
||||
template <class T> friend class serialization::AbstractTypeReader;
|
||||
|
||||
CXXRecordDecl *Decl;
|
||||
|
||||
|
@ -5843,6 +5852,7 @@ class ObjCInterfaceType : public ObjCObjectType {
|
|||
friend class ASTContext; // ASTContext creates these.
|
||||
friend class ASTReader;
|
||||
friend class ObjCInterfaceDecl;
|
||||
template <class T> friend class serialization::AbstractTypeReader;
|
||||
|
||||
mutable ObjCInterfaceDecl *Decl;
|
||||
|
||||
|
|
|
@ -0,0 +1,812 @@
|
|||
//==--- TypeProperties.td - Type property definitions ---------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "PropertiesBase.td"
|
||||
include "../Basic/TypeNodes.td"
|
||||
|
||||
let Class = ComplexType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{ return ctx.getComplexType(elementType); }]>;
|
||||
}
|
||||
|
||||
let Class = PointerType in {
|
||||
def : Property<"pointeeType", QualType> {
|
||||
let Read = [{ node->getPointeeType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{ return ctx.getPointerType(pointeeType); }]>;
|
||||
}
|
||||
|
||||
let Class = AdjustedType in {
|
||||
def : Property<"originalType", QualType> {
|
||||
let Read = [{ node->getOriginalType() }];
|
||||
}
|
||||
def : Property<"adjustedType", QualType> {
|
||||
let Read = [{ node->getAdjustedType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{ return ctx.getAdjustedType(originalType, adjustedType); }]>;
|
||||
}
|
||||
|
||||
let Class = DecayedType in {
|
||||
def : Override {
|
||||
// We don't need to serialize the adjusted type because we can always
|
||||
// derive it by decaying the original type.
|
||||
let IgnoredProperties = [ "adjustedType" ];
|
||||
}
|
||||
|
||||
def : Creator<[{ return ctx.getAdjustedParameterType(originalType); }]>;
|
||||
}
|
||||
|
||||
let Class = BlockPointerType in {
|
||||
def : Property<"pointeeType", QualType> {
|
||||
let Read = [{ node->getPointeeType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{ return ctx.getBlockPointerType(pointeeType); }]>;
|
||||
}
|
||||
|
||||
let Class = ReferenceType in {
|
||||
def : Property<"pointeeTypeAsWritten", QualType> {
|
||||
let Read = [{ node->getPointeeTypeAsWritten() }];
|
||||
}
|
||||
}
|
||||
|
||||
let Class = LValueReferenceType in {
|
||||
def : Property<"isSpelledAsLValue", Bool> {
|
||||
let Read = [{ node->isSpelledAsLValue() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getLValueReferenceType(pointeeTypeAsWritten,
|
||||
isSpelledAsLValue);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = RValueReferenceType in {
|
||||
def : Creator<[{
|
||||
return ctx.getRValueReferenceType(pointeeTypeAsWritten);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = MemberPointerType in {
|
||||
def : Property<"pointeeType", QualType> {
|
||||
let Read = [{ node->getPointeeType() }];
|
||||
}
|
||||
def : Property<"baseType", QualType> {
|
||||
let Read = [{ QualType(node->getClass(), 0) }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getMemberPointerType(pointeeType, baseType.getTypePtr());
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ArrayType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
def : Property<"sizeModifier", ArraySizeModifier> {
|
||||
let Read = [{ node->getSizeModifier() }];
|
||||
}
|
||||
def : Property<"indexQualifiers", Qualifiers> {
|
||||
let Read = [{ Qualifiers::fromCVRMask(node->getIndexTypeCVRQualifiers()) }];
|
||||
}
|
||||
}
|
||||
|
||||
let Class = ConstantArrayType in {
|
||||
def : Property<"sizeValue", APInt> {
|
||||
let Read = [{ node->getSize() }];
|
||||
}
|
||||
def : Property<"size", ExprRef> {
|
||||
let Read = [{ node->getSizeExpr() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getConstantArrayType(elementType, sizeValue, size,
|
||||
sizeModifier,
|
||||
indexQualifiers.getCVRQualifiers());
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = IncompleteArrayType in {
|
||||
def : Creator<[{
|
||||
return ctx.getIncompleteArrayType(elementType, sizeModifier,
|
||||
indexQualifiers.getCVRQualifiers());
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = VariableArrayType in {
|
||||
def : Property<"leftBracketLoc", SourceLocation> {
|
||||
let Read = [{ node->getLBracketLoc() }];
|
||||
}
|
||||
def : Property<"rightBracketLoc", SourceLocation> {
|
||||
let Read = [{ node->getRBracketLoc() }];
|
||||
}
|
||||
def : Property<"size", ExprRef> {
|
||||
let Read = [{ node->getSizeExpr() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getVariableArrayType(elementType, size, sizeModifier,
|
||||
indexQualifiers.getCVRQualifiers(),
|
||||
SourceRange(leftBracketLoc,
|
||||
rightBracketLoc));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentSizedArrayType in {
|
||||
def : Property<"size", ExprRef> {
|
||||
let Read = [{ node->getSizeExpr() }];
|
||||
}
|
||||
def : Property<"leftBracketLoc", SourceLocation> {
|
||||
let Read = [{ node->getLBracketLoc() }];
|
||||
}
|
||||
def : Property<"rightBracketLoc", SourceLocation> {
|
||||
let Read = [{ node->getRBracketLoc() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentSizedArrayType(elementType, size, sizeModifier,
|
||||
indexQualifiers.getCVRQualifiers(),
|
||||
SourceRange(leftBracketLoc,
|
||||
rightBracketLoc));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = VectorType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
def : Property<"numElements", UInt32> {
|
||||
let Read = [{ node->getNumElements() }];
|
||||
}
|
||||
def : Property<"vectorKind", VectorKind> {
|
||||
let Read = [{ node->getVectorKind() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getVectorType(elementType, numElements, vectorKind);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentVectorType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
def : Property<"size", ExprRef> {
|
||||
let Read = [{ node->getSizeExpr() }];
|
||||
}
|
||||
def : Property<"attributeLoc", SourceLocation> {
|
||||
let Read = [{ node->getAttributeLoc() }];
|
||||
}
|
||||
def : Property<"vectorKind", VectorKind> {
|
||||
let Read = [{ node->getVectorKind() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentVectorType(elementType, size, attributeLoc,
|
||||
vectorKind);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ExtVectorType in {
|
||||
def : Override {
|
||||
let IgnoredProperties = [ "vectorKind" ];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getExtVectorType(elementType, numElements);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentSizedExtVectorType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
def : Property<"size", ExprRef> {
|
||||
let Read = [{ node->getSizeExpr() }];
|
||||
}
|
||||
def : Property<"attributeLoc", SourceLocation> {
|
||||
let Read = [{ node->getAttributeLoc() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentSizedExtVectorType(elementType, size, attributeLoc);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = FunctionType in {
|
||||
def : Property<"returnType", QualType> {
|
||||
let Read = [{ node->getReturnType() }];
|
||||
}
|
||||
def : Property<"noReturn", Bool> {
|
||||
let Read = [{ node->getExtInfo().getNoReturn() }];
|
||||
}
|
||||
def : Property<"hasRegParm", Bool> {
|
||||
let Read = [{ node->getExtInfo().getHasRegParm() }];
|
||||
}
|
||||
def : Property<"regParm", UInt32> {
|
||||
let Read = [{ node->getExtInfo().getRegParm() }];
|
||||
}
|
||||
def : Property<"callingConvention", CallingConv> {
|
||||
let Read = [{ node->getExtInfo().getCC() }];
|
||||
}
|
||||
def : Property<"producesResult", Bool> {
|
||||
let Read = [{ node->getExtInfo().getProducesResult() }];
|
||||
}
|
||||
def : Property<"noCallerSavedRegs", Bool> {
|
||||
let Read = [{ node->getExtInfo().getNoCallerSavedRegs() }];
|
||||
}
|
||||
def : Property<"noCfCheck", Bool> {
|
||||
let Read = [{ node->getExtInfo().getNoCfCheck() }];
|
||||
}
|
||||
}
|
||||
|
||||
let Class = FunctionNoProtoType in {
|
||||
def : Creator<[{
|
||||
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
|
||||
callingConvention, producesResult,
|
||||
noCallerSavedRegs, noCfCheck);
|
||||
return ctx.getFunctionNoProtoType(returnType, extInfo);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = FunctionProtoType in {
|
||||
def : Property<"variadic", Bool> {
|
||||
let Read = [{ node->isVariadic() }];
|
||||
}
|
||||
def : Property<"trailingReturn", Bool> {
|
||||
let Read = [{ node->hasTrailingReturn() }];
|
||||
}
|
||||
def : Property<"methodQualifiers", Qualifiers> {
|
||||
let Read = [{ node->getMethodQuals() }];
|
||||
}
|
||||
def : Property<"refQualifier", RefQualifierKind> {
|
||||
let Read = [{ node->getRefQualifier() }];
|
||||
}
|
||||
def : Property<"exceptionSpecifier", ExceptionSpecInfo> {
|
||||
let Read = [{ node->getExceptionSpecInfo() }];
|
||||
}
|
||||
def : Property<"parameters", Array<QualType>> {
|
||||
let Read = [{ node->getParamTypes() }];
|
||||
}
|
||||
def : Property<"extParameterInfo", Array<ExtParameterInfo>> {
|
||||
let Read = [{ node->hasExtParameterInfos()
|
||||
? node->getExtParameterInfos()
|
||||
: llvm::ArrayRef<FunctionProtoType::ExtParameterInfo>() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
|
||||
callingConvention, producesResult,
|
||||
noCallerSavedRegs, noCfCheck);
|
||||
FunctionProtoType::ExtProtoInfo epi;
|
||||
epi.ExtInfo = extInfo;
|
||||
epi.Variadic = variadic;
|
||||
epi.HasTrailingReturn = trailingReturn;
|
||||
epi.TypeQuals = methodQualifiers;
|
||||
epi.RefQualifier = refQualifier;
|
||||
epi.ExceptionSpec = exceptionSpecifier;
|
||||
epi.ExtParameterInfos =
|
||||
extParameterInfo.empty() ? nullptr : extParameterInfo.data();
|
||||
return ctx.getFunctionType(returnType, parameters, epi);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = AtomicType in {
|
||||
def : Property<"valueType", QualType> {
|
||||
let Read = [{ node->getValueType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getAtomicType(valueType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = UnresolvedUsingType in {
|
||||
def : Property<"declaration", DeclRef> {
|
||||
let Read = [{ node->getDecl() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getTypeDeclType(cast<UnresolvedUsingTypenameDecl>(declaration));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TypedefType in {
|
||||
def : Property<"declaration", DeclRef> {
|
||||
let Read = [{ node->getDecl() }];
|
||||
}
|
||||
def : Property<"canonicalType", Optional<QualType>> {
|
||||
let Read = [{ makeOptionalFromNullable(node->getCanonicalTypeInternal()) }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
QualType finalCanonicalType =
|
||||
canonicalType ? ctx.getCanonicalType(*canonicalType)
|
||||
: QualType();
|
||||
return ctx.getTypedefType(cast<TypedefNameDecl>(declaration),
|
||||
finalCanonicalType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TypeOfExprType in {
|
||||
def : Property<"expression", ExprRef> {
|
||||
let Read = [{ node->getUnderlyingExpr() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getTypeOfExprType(expression);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TypeOfType in {
|
||||
def : Property<"underlyingType", QualType> {
|
||||
let Read = [{ node->getUnderlyingType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getTypeOfType(underlyingType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DecltypeType in {
|
||||
def : Property<"underlyingType", QualType> {
|
||||
let Read = [{ node->getUnderlyingType() }];
|
||||
}
|
||||
def : Property<"expression", ExprRef> {
|
||||
let Read = [{ node->getUnderlyingExpr() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDecltypeType(expression, underlyingType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = UnaryTransformType in {
|
||||
def : Property<"baseType", QualType> {
|
||||
let Read = [{ node->getBaseType() }];
|
||||
}
|
||||
def : Property<"underlyingType", QualType> {
|
||||
let Read = [{ node->getUnderlyingType() }];
|
||||
}
|
||||
def : Property<"transform", UnaryTypeTransformKind> {
|
||||
let Read = [{ node->getUTTKind() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getUnaryTransformType(baseType, underlyingType, transform);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = AutoType in {
|
||||
def : Property<"deducedType", Optional<QualType>> {
|
||||
let Read = [{ makeOptionalFromNullable(node->getDeducedType()) }];
|
||||
}
|
||||
def : Property<"keyword", AutoTypeKeyword> {
|
||||
let Read = [{ node->getKeyword() }];
|
||||
}
|
||||
// FIXME: better enumerated value
|
||||
// Only really required when the deduced type is null
|
||||
def : Property<"dependence", UInt32> {
|
||||
let Read = [{ !node->getDeducedType().isNull() ? 0 :
|
||||
node->containsUnexpandedParameterPack() ? 2 :
|
||||
node->isDependentType() ? 1 : 0 }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getAutoType(makeNullableFromOptional(deducedType), keyword,
|
||||
/*isDependentWithoutDeducedType*/ dependence > 0,
|
||||
/*isPackWithoutDeducedType*/ dependence > 1);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DeducedTemplateSpecializationType in {
|
||||
def : Property<"templateName", Optional<TemplateName>> {
|
||||
let Read = [{ makeOptionalFromNullable(node->getTemplateName()) }];
|
||||
}
|
||||
def : Property<"deducedType", QualType> {
|
||||
let Read = [{ node->getDeducedType() }];
|
||||
}
|
||||
// Only really required when the deduced type is null
|
||||
def : Property<"dependent", Bool> {
|
||||
let Read = [{ !node->getDeducedType().isNull()
|
||||
? false : node->isDependentType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDeducedTemplateSpecializationType(
|
||||
makeNullableFromOptional(templateName),
|
||||
deducedType, dependent);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TagType in {
|
||||
def : Property<"dependent", Bool> {
|
||||
let Read = [{ node->isDependentType() }];
|
||||
}
|
||||
def : Property<"declaration", DeclRef> {
|
||||
// Serializing a reference to the canonical declaration is apparently
|
||||
// necessary to make module-merging work.
|
||||
let Read = [{ node->getDecl()->getCanonicalDecl() }];
|
||||
}
|
||||
}
|
||||
|
||||
let Class = EnumType in {
|
||||
def : Creator<[{
|
||||
QualType result = ctx.getEnumType(cast<EnumDecl>(declaration));
|
||||
const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
|
||||
return result;
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = RecordType in {
|
||||
def : Creator<[{
|
||||
auto record = cast<RecordDecl>(declaration);
|
||||
QualType result = ctx.getRecordType(record);
|
||||
const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
|
||||
return result;
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ElaboratedType in {
|
||||
def : Property<"keyword", ElaboratedTypeKeyword> {
|
||||
let Read = [{ node->getKeyword() }];
|
||||
}
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ node->getQualifier() }];
|
||||
}
|
||||
def : Property<"namedType", QualType> {
|
||||
let Read = [{ node->getNamedType() }];
|
||||
}
|
||||
def : Property<"ownedTag", Optional<TagDeclRef>> {
|
||||
let Read = [{ makeOptionalFromPointer(node->getOwnedTagDecl()) }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getElaboratedType(keyword, qualifier, namedType,
|
||||
makePointerFromOptional(ownedTag));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = InjectedClassNameType in {
|
||||
def : Property<"declaration", DeclRef> {
|
||||
// FIXME: drilling down to the canonical declaration is what the
|
||||
// existing serialization code was doing, but it's not clear why.
|
||||
let Read = [{ node->getDecl()->getCanonicalDecl() }];
|
||||
}
|
||||
def : Property<"injectedSpecializationType", QualType> {
|
||||
let Read = [{ node->getInjectedSpecializationType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
// FIXME: ASTContext::getInjectedClassNameType is not currently suitable
|
||||
// for AST reading, too much interdependencies.
|
||||
const Type *T = nullptr;
|
||||
auto typeDecl = cast<CXXRecordDecl>(declaration);
|
||||
for (auto *DI = typeDecl; DI; DI = DI->getPreviousDecl()) {
|
||||
if (const Type *existing = DI->getTypeForDecl()) {
|
||||
T = existing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!T) {
|
||||
T = new (ctx, TypeAlignment)
|
||||
InjectedClassNameType(typeDecl, injectedSpecializationType);
|
||||
for (auto *DI = typeDecl; DI; DI = DI->getPreviousDecl())
|
||||
DI->setTypeForDecl(T);
|
||||
}
|
||||
return QualType(T, 0);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ParenType in {
|
||||
def : Property<"innerType", QualType> {
|
||||
let Read = [{ node->getInnerType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getParenType(innerType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = MacroQualifiedType in {
|
||||
def : Property<"underlyingType", QualType> {
|
||||
let Read = [{ node->getUnderlyingType() }];
|
||||
}
|
||||
def : Property<"macroIdentifier", Identifier> {
|
||||
let Read = [{ node->getMacroIdentifier() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getMacroQualifiedType(underlyingType, macroIdentifier);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = AttributedType in {
|
||||
def : Property<"modifiedType", QualType> {
|
||||
let Read = [{ node->getModifiedType() }];
|
||||
}
|
||||
def : Property<"equivalentType", QualType> {
|
||||
let Read = [{ node->getEquivalentType() }];
|
||||
}
|
||||
def : Property<"attribute", AttrKind> {
|
||||
let Read = [{ node->getAttrKind() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getAttributedType(attribute, modifiedType, equivalentType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentAddressSpaceType in {
|
||||
def : Property<"pointeeType", QualType> {
|
||||
let Read = [{ node->getPointeeType() }];
|
||||
}
|
||||
def : Property<"addressSpace", ExprRef> {
|
||||
let Read = [{ node->getAddrSpaceExpr() }];
|
||||
}
|
||||
def : Property<"attributeLoc", SourceLocation> {
|
||||
let Read = [{ node->getAttributeLoc() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentAddressSpaceType(pointeeType, addressSpace,
|
||||
attributeLoc);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TemplateSpecializationType in {
|
||||
def : Property<"dependent", Bool> {
|
||||
let Read = [{ node->isDependentType() }];
|
||||
}
|
||||
def : Property<"templateName", TemplateName> {
|
||||
let Read = [{ node->getTemplateName() }];
|
||||
}
|
||||
def : Property<"templateArguments", Array<TemplateArgument>> {
|
||||
let Read = [{ node->template_arguments() }];
|
||||
}
|
||||
def : Property<"underlyingType", Optional<QualType>> {
|
||||
let Read = [{
|
||||
node->isTypeAlias()
|
||||
? llvm::Optional<QualType>(node->getAliasedType())
|
||||
: node->isCanonicalUnqualified()
|
||||
? llvm::None
|
||||
: llvm::Optional<QualType>(node->getCanonicalTypeInternal())
|
||||
}];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
QualType result;
|
||||
if (!underlyingType.hasValue()) {
|
||||
result = ctx.getCanonicalTemplateSpecializationType(templateName,
|
||||
templateArguments);
|
||||
} else {
|
||||
result = ctx.getTemplateSpecializationType(templateName,
|
||||
templateArguments,
|
||||
*underlyingType);
|
||||
}
|
||||
const_cast<Type*>(result.getTypePtr())->setDependent(dependent);
|
||||
return result;
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentTemplateSpecializationType in {
|
||||
def : Property<"keyword", ElaboratedTypeKeyword> {
|
||||
let Read = [{ node->getKeyword() }];
|
||||
}
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ node->getQualifier() }];
|
||||
}
|
||||
def : Property<"name", Identifier> {
|
||||
let Read = [{ node->getIdentifier() }];
|
||||
}
|
||||
def : Property<"templateArguments", Array<TemplateArgument>> {
|
||||
let Read = [{ node->template_arguments() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentTemplateSpecializationType(keyword, qualifier,
|
||||
name, templateArguments);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = TemplateTypeParmType in {
|
||||
def : Property<"depth", UInt32> {
|
||||
let Read = [{ node->getDepth() }];
|
||||
}
|
||||
def : Property<"index", UInt32> {
|
||||
let Read = [{ node->getIndex() }];
|
||||
}
|
||||
def : Property<"isParameterPack", Bool> {
|
||||
let Read = [{ node->isParameterPack() }];
|
||||
}
|
||||
def : Property<"declaration", Optional<TemplateTypeParmDeclRef>> {
|
||||
let Read = [{ makeOptionalFromPointer(node->getDecl()) }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getTemplateTypeParmType(depth, index, isParameterPack,
|
||||
makePointerFromOptional(declaration));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = SubstTemplateTypeParmType in {
|
||||
def : Property<"replacedParameter", QualType> {
|
||||
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
|
||||
}
|
||||
def : Property<"replacementType", QualType> {
|
||||
let Read = [{ node->getReplacementType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
// The call to getCanonicalType here existed in ASTReader.cpp, too.
|
||||
return ctx.getSubstTemplateTypeParmType(
|
||||
cast<TemplateTypeParmType>(replacedParameter),
|
||||
ctx.getCanonicalType(replacementType));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = PackExpansionType in {
|
||||
def : Property<"pattern", QualType> {
|
||||
let Read = [{ node->getPattern() }];
|
||||
}
|
||||
def : Property<"numExpansions", Optional<UInt32>> {
|
||||
let Read = [{ node->getNumExpansions() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getPackExpansionType(pattern, numExpansions);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = SubstTemplateTypeParmPackType in {
|
||||
def : Property<"replacedParameter", QualType> {
|
||||
let Read = [{ QualType(node->getReplacedParameter(), 0) }];
|
||||
}
|
||||
def : Property<"replacementPack", TemplateArgument> {
|
||||
let Read = [{ node->getArgumentPack() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getSubstTemplateTypeParmPackType(
|
||||
cast<TemplateTypeParmType>(replacedParameter),
|
||||
replacementPack);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = BuiltinType in {
|
||||
def : Property<"kind", BuiltinTypeKind> {
|
||||
let Read = [{ node->getKind() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
switch (kind) {
|
||||
#define IMAGE_TYPE(IMGTYPE, ID, SINGLETON_ID, ACCESS, SUFFIX) \
|
||||
case BuiltinType::ID: return ctx.SINGLETON_ID;
|
||||
#include "clang/Basic/OpenCLImageTypes.def"
|
||||
|
||||
#define EXT_OPAQUE_TYPE(EXTTYPE, ID, EXT) \
|
||||
case BuiltinType::ID: return ctx.ID##Ty;
|
||||
#include "clang/Basic/OpenCLExtensionTypes.def"
|
||||
|
||||
#define SVE_TYPE(NAME, ID, SINGLETON_ID) \
|
||||
case BuiltinType::ID: return ctx.SINGLETON_ID;
|
||||
#include "clang/Basic/AArch64SVEACLETypes.def"
|
||||
|
||||
#define BUILTIN_TYPE(ID, SINGLETON_ID) \
|
||||
case BuiltinType::ID: return ctx.SINGLETON_ID;
|
||||
#include "clang/AST/BuiltinTypes.def"
|
||||
}
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = DependentNameType in {
|
||||
def : Property<"keyword", ElaboratedTypeKeyword> {
|
||||
let Read = [{ node->getKeyword() }];
|
||||
}
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ node->getQualifier() }];
|
||||
}
|
||||
def : Property<"name", Identifier> {
|
||||
let Read = [{ node->getIdentifier() }];
|
||||
}
|
||||
def : Property<"underlyingType", Optional<QualType>> {
|
||||
let Read = [{
|
||||
node->isCanonicalUnqualified()
|
||||
? llvm::None
|
||||
: llvm::Optional<QualType>(node->getCanonicalTypeInternal())
|
||||
}];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
QualType canon = (underlyingType
|
||||
? ctx.getCanonicalType(*underlyingType)
|
||||
: QualType());
|
||||
return ctx.getDependentNameType(keyword, qualifier, name, canon);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ObjCObjectType in {
|
||||
def : Property<"baseType", QualType> {
|
||||
let Read = [{ node->getBaseType() }];
|
||||
}
|
||||
def : Property<"typeArgsAsWritten", Array<QualType>> {
|
||||
let Read = [{ node->getTypeArgsAsWritten() }];
|
||||
}
|
||||
def : Property<"qualifiers", Array<ObjCProtocolDeclRef>> {
|
||||
let Read = [{ node->getProtocols() }];
|
||||
}
|
||||
def : Property<"isKindOfTypeAsWritten", Bool> {
|
||||
let Read = [{ node->isKindOfTypeAsWritten() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getObjCObjectType(baseType, typeArgsAsWritten, qualifiers,
|
||||
isKindOfTypeAsWritten);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ObjCInterfaceType in {
|
||||
// We don't actually want any of the properties of the superclass.
|
||||
def : Override {
|
||||
let IgnoredProperties = [ "baseType", "typeArgsAsWritten",
|
||||
"qualifiers", "isKindOfTypeAsWritten" ];
|
||||
}
|
||||
|
||||
def : Property<"declaration", DeclRef> {
|
||||
// FIXME: drilling down to the canonical declaration is what the
|
||||
// existing serialization code was doing, but it's not clear why.
|
||||
let Read = [{ node->getDecl()->getCanonicalDecl() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getObjCInterfaceType(
|
||||
cast<ObjCInterfaceDecl>(declaration->getCanonicalDecl()));
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ObjCTypeParamType in {
|
||||
def : Property<"declaration", ObjCTypeParamDeclRef> {
|
||||
let Read = [{ node->getDecl() }];
|
||||
}
|
||||
def : Property<"qualifiers", Array<ObjCProtocolDeclRef>> {
|
||||
let Read = [{ node->getProtocols() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getObjCTypeParamType(declaration, qualifiers);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = ObjCObjectPointerType in {
|
||||
def : Property<"pointeeType", QualType> {
|
||||
let Read = [{ node->getPointeeType() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getObjCObjectPointerType(pointeeType);
|
||||
}]>;
|
||||
}
|
||||
|
||||
let Class = PipeType in {
|
||||
def : Property<"elementType", QualType> {
|
||||
let Read = [{ node->getElementType() }];
|
||||
}
|
||||
def : Property<"isReadOnly", Bool> {
|
||||
let Read = [{ node->isReadOnly() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getPipeType(elementType, isReadOnly);
|
||||
}]>;
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
#ifndef LLVM_CLANG_SERIALIZATION_ASTREADER_H
|
||||
#define LLVM_CLANG_SERIALIZATION_ASTREADER_H
|
||||
|
||||
#include "clang/AST/AbstractBasicReader.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
|
@ -2281,7 +2282,8 @@ public:
|
|||
};
|
||||
|
||||
/// An object for streaming information from a record.
|
||||
class ASTRecordReader {
|
||||
class ASTRecordReader
|
||||
: public serialization::DataStreamBasicReader<ASTRecordReader> {
|
||||
using ModuleFile = serialization::ModuleFile;
|
||||
|
||||
ASTReader *Reader;
|
||||
|
@ -2294,7 +2296,8 @@ class ASTRecordReader {
|
|||
|
||||
public:
|
||||
/// Construct an ASTRecordReader that uses the default encoding scheme.
|
||||
ASTRecordReader(ASTReader &Reader, ModuleFile &F) : Reader(&Reader), F(&F) {}
|
||||
ASTRecordReader(ASTReader &Reader, ModuleFile &F)
|
||||
: DataStreamBasicReader(Reader.getContext()), Reader(&Reader), F(&F) {}
|
||||
|
||||
/// Reads a record with id AbbrevID from Cursor, resetting the
|
||||
/// internal state.
|
||||
|
@ -2367,8 +2370,9 @@ public:
|
|||
static_cast<ExplicitSpecKind>(Kind));
|
||||
}
|
||||
|
||||
FunctionProtoType::ExceptionSpecInfo
|
||||
readExceptionSpecInfo(SmallVectorImpl<QualType> &ExceptionStorage);
|
||||
/// Read information about an exception specification (inherited).
|
||||
//FunctionProtoType::ExceptionSpecInfo
|
||||
//readExceptionSpecInfo(SmallVectorImpl<QualType> &ExceptionStorage);
|
||||
|
||||
/// Get the global offset corresponding to a local offset.
|
||||
uint64_t getGlobalBitOffset(uint32_t LocalOffset) {
|
||||
|
@ -2377,6 +2381,7 @@ public:
|
|||
|
||||
/// Reads a statement.
|
||||
Stmt *readStmt() { return Reader->ReadStmt(*F); }
|
||||
Stmt *readStmtRef() { return readStmt(); /* FIXME: readSubStmt? */ }
|
||||
|
||||
/// Reads an expression.
|
||||
Expr *readExpr() { return Reader->ReadExpr(*F); }
|
||||
|
@ -2426,6 +2431,9 @@ public:
|
|||
QualType readType() {
|
||||
return Reader->readType(*F, Record, Idx);
|
||||
}
|
||||
QualType readQualType() {
|
||||
return readType();
|
||||
}
|
||||
|
||||
/// Reads a declaration ID from the given position in this record.
|
||||
///
|
||||
|
@ -2439,6 +2447,9 @@ public:
|
|||
Decl *readDecl() {
|
||||
return Reader->ReadDecl(*F, Record, Idx);
|
||||
}
|
||||
Decl *readDeclRef() {
|
||||
return readDecl();
|
||||
}
|
||||
|
||||
/// Reads a declaration from the given position in the record,
|
||||
/// advancing Idx.
|
||||
|
@ -2460,21 +2471,22 @@ public:
|
|||
}
|
||||
|
||||
/// Read a declaration name, advancing Idx.
|
||||
DeclarationName readDeclarationName();
|
||||
// DeclarationName readDeclarationName(); (inherited)
|
||||
DeclarationNameLoc readDeclarationNameLoc(DeclarationName Name);
|
||||
DeclarationNameInfo readDeclarationNameInfo();
|
||||
|
||||
void readQualifierInfo(QualifierInfo &Info);
|
||||
|
||||
NestedNameSpecifier *readNestedNameSpecifier();
|
||||
/// Return a nested name specifier, advancing Idx.
|
||||
// NestedNameSpecifier *readNestedNameSpecifier(); (inherited)
|
||||
|
||||
NestedNameSpecifierLoc readNestedNameSpecifierLoc();
|
||||
|
||||
/// Read a template name, advancing Idx.
|
||||
TemplateName readTemplateName();
|
||||
// TemplateName readTemplateName(); (inherited)
|
||||
|
||||
/// Read a template argument, advancing Idx.
|
||||
TemplateArgument readTemplateArgument(bool Canonicalize = false);
|
||||
/// Read a template argument, advancing Idx. (inherited)
|
||||
// TemplateArgument readTemplateArgument(bool Canonicalize = false);
|
||||
|
||||
/// Read a template parameter list, advancing Idx.
|
||||
TemplateParameterList *readTemplateParameterList();
|
||||
|
@ -2510,10 +2522,10 @@ public:
|
|||
APValue readAPValue();
|
||||
|
||||
/// Read an integral value, advancing Idx.
|
||||
llvm::APInt readAPInt();
|
||||
// llvm::APInt readAPInt(); (inherited)
|
||||
|
||||
/// Read a signed integral value, advancing Idx.
|
||||
llvm::APSInt readAPSInt();
|
||||
// llvm::APSInt readAPSInt(); (inherited)
|
||||
|
||||
/// Read a floating-point value, advancing Idx.
|
||||
llvm::APFloat readAPFloat(const llvm::fltSemantics &Sem);
|
||||
|
@ -2521,6 +2533,16 @@ public:
|
|||
/// Read a boolean value, advancing Idx.
|
||||
bool readBool() { return readInt() != 0; }
|
||||
|
||||
/// Read a 32-bit unsigned value; required to satisfy BasicReader.
|
||||
uint32_t readUInt32() {
|
||||
return uint32_t(readInt());
|
||||
}
|
||||
|
||||
/// Read a 64-bit unsigned value; required to satisfy BasicReader.
|
||||
uint64_t readUInt64() {
|
||||
return readInt();
|
||||
}
|
||||
|
||||
/// Read a string, advancing Idx.
|
||||
std::string readString() {
|
||||
return Reader->ReadString(Record, Idx);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#ifndef LLVM_CLANG_SERIALIZATION_ASTWRITER_H
|
||||
#define LLVM_CLANG_SERIALIZATION_ASTWRITER_H
|
||||
|
||||
#include "clang/AST/AbstractBasicWriter.h"
|
||||
#include "clang/AST/ASTMutationListener.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
|
@ -745,7 +746,8 @@ private:
|
|||
};
|
||||
|
||||
/// An object for streaming information to a record.
|
||||
class ASTRecordWriter {
|
||||
class ASTRecordWriter
|
||||
: public serialization::DataStreamBasicWriter<ASTRecordWriter> {
|
||||
ASTWriter *Writer;
|
||||
ASTWriter::RecordDataImpl *Record;
|
||||
|
||||
|
@ -839,6 +841,9 @@ public:
|
|||
void AddStmt(Stmt *S) {
|
||||
StmtsToEmit.push_back(S);
|
||||
}
|
||||
void writeStmtRef(const Stmt *S) {
|
||||
AddStmt(const_cast<Stmt*>(S));
|
||||
}
|
||||
|
||||
/// Add a definition for the given function to the queue of statements
|
||||
/// to emit.
|
||||
|
@ -848,17 +853,36 @@ public:
|
|||
void AddSourceLocation(SourceLocation Loc) {
|
||||
return Writer->AddSourceLocation(Loc, *Record);
|
||||
}
|
||||
void writeSourceLocation(SourceLocation Loc) {
|
||||
AddSourceLocation(Loc);
|
||||
}
|
||||
|
||||
/// Emit a source range.
|
||||
void AddSourceRange(SourceRange Range) {
|
||||
return Writer->AddSourceRange(Range, *Record);
|
||||
}
|
||||
|
||||
void writeBool(bool Value) {
|
||||
Record->push_back(Value);
|
||||
}
|
||||
|
||||
void writeUInt32(uint32_t Value) {
|
||||
Record->push_back(Value);
|
||||
}
|
||||
|
||||
void writeUInt64(uint64_t Value) {
|
||||
Record->push_back(Value);
|
||||
}
|
||||
|
||||
/// Emit an integral value.
|
||||
void AddAPInt(const llvm::APInt &Value);
|
||||
void AddAPInt(const llvm::APInt &Value) {
|
||||
writeAPInt(Value);
|
||||
}
|
||||
|
||||
/// Emit a signed integral value.
|
||||
void AddAPSInt(const llvm::APSInt &Value);
|
||||
void AddAPSInt(const llvm::APSInt &Value) {
|
||||
writeAPSInt(Value);
|
||||
}
|
||||
|
||||
/// Emit a floating-point value.
|
||||
void AddAPFloat(const llvm::APFloat &Value);
|
||||
|
@ -870,9 +894,15 @@ public:
|
|||
void AddIdentifierRef(const IdentifierInfo *II) {
|
||||
return Writer->AddIdentifierRef(II, *Record);
|
||||
}
|
||||
void writeIdentifier(const IdentifierInfo *II) {
|
||||
AddIdentifierRef(II);
|
||||
}
|
||||
|
||||
/// Emit a Selector (which is a smart pointer reference).
|
||||
void AddSelectorRef(Selector S);
|
||||
void writeSelector(Selector sel) {
|
||||
AddSelectorRef(sel);
|
||||
}
|
||||
|
||||
/// Emit a CXXTemporary.
|
||||
void AddCXXTemporary(const CXXTemporary *Temp);
|
||||
|
@ -887,6 +917,9 @@ public:
|
|||
void AddTypeRef(QualType T) {
|
||||
return Writer->AddTypeRef(T, *Record);
|
||||
}
|
||||
void writeQualType(QualType T) {
|
||||
AddTypeRef(T);
|
||||
}
|
||||
|
||||
/// Emits a reference to a declarator info.
|
||||
void AddTypeSourceInfo(TypeSourceInfo *TInfo);
|
||||
|
@ -909,9 +942,14 @@ public:
|
|||
void AddDeclRef(const Decl *D) {
|
||||
return Writer->AddDeclRef(D, *Record);
|
||||
}
|
||||
void writeDeclRef(const Decl *D) {
|
||||
AddDeclRef(D);
|
||||
}
|
||||
|
||||
/// Emit a declaration name.
|
||||
void AddDeclarationName(DeclarationName Name);
|
||||
void AddDeclarationName(DeclarationName Name) {
|
||||
writeDeclarationName(Name);
|
||||
}
|
||||
|
||||
void AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,
|
||||
DeclarationName Name);
|
||||
|
@ -920,16 +958,22 @@ public:
|
|||
void AddQualifierInfo(const QualifierInfo &Info);
|
||||
|
||||
/// Emit a nested name specifier.
|
||||
void AddNestedNameSpecifier(NestedNameSpecifier *NNS);
|
||||
void AddNestedNameSpecifier(NestedNameSpecifier *NNS) {
|
||||
writeNestedNameSpecifier(NNS);
|
||||
}
|
||||
|
||||
/// Emit a nested name specifier with source-location information.
|
||||
void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
|
||||
|
||||
/// Emit a template name.
|
||||
void AddTemplateName(TemplateName Name);
|
||||
void AddTemplateName(TemplateName Name) {
|
||||
writeTemplateName(Name);
|
||||
}
|
||||
|
||||
/// Emit a template argument.
|
||||
void AddTemplateArgument(const TemplateArgument &Arg);
|
||||
void AddTemplateArgument(const TemplateArgument &Arg) {
|
||||
writeTemplateArgument(Arg);
|
||||
}
|
||||
|
||||
/// Emit a template parameter list.
|
||||
void AddTemplateParameterList(const TemplateParameterList *TemplateParams);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "clang/Serialization/ASTReader.h"
|
||||
#include "ASTCommon.h"
|
||||
#include "ASTReaderInternals.h"
|
||||
#include "clang/AST/AbstractTypeReader.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/ASTMutationListener.h"
|
||||
|
@ -6316,16 +6317,13 @@ ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {
|
|||
return RecordLocation(M, M->TypeOffsets[Index - M->BaseTypeIndex]);
|
||||
}
|
||||
|
||||
static FunctionType::ExtInfo readFunctionExtInfo(ASTRecordReader &Record) {
|
||||
bool noreturn = Record.readBool();
|
||||
bool hasregparm = Record.readBool();
|
||||
unsigned regparm = Record.readInt();
|
||||
auto cc = static_cast<CallingConv>(Record.readInt());
|
||||
bool producesResult = Record.readBool();
|
||||
bool nocallersavedregs = Record.readBool();
|
||||
bool nocfcheck = Record.readBool();
|
||||
return FunctionType::ExtInfo(noreturn, hasregparm, regparm, cc,
|
||||
producesResult, nocallersavedregs, nocfcheck);
|
||||
static llvm::Optional<Type::TypeClass> getTypeClassForCode(TypeCode code) {
|
||||
switch (code) {
|
||||
#define TYPE_BIT_CODE(CLASS_ID, CODE_ID, CODE_VALUE) \
|
||||
case TYPE_##CODE_ID: return Type::CLASS_ID;
|
||||
#include "clang/Serialization/TypeBitCodes.def"
|
||||
default: return llvm::None;
|
||||
}
|
||||
}
|
||||
|
||||
/// Read and return the type with the given index..
|
||||
|
@ -6365,534 +6363,20 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
|
|||
Error(Code.takeError());
|
||||
return QualType();
|
||||
}
|
||||
switch ((TypeCode) Code.get()) {
|
||||
case TYPE_EXT_QUAL: {
|
||||
if (Record.size() != 2) {
|
||||
Error("Incorrect encoding of extended qualifier type");
|
||||
return QualType();
|
||||
}
|
||||
QualType Base = Record.readType();
|
||||
Qualifiers Quals = Record.readQualifiers();
|
||||
return Context.getQualifiedType(Base, Quals);
|
||||
if (Code.get() == TYPE_EXT_QUAL) {
|
||||
QualType baseType = Record.readQualType();
|
||||
Qualifiers quals = Record.readQualifiers();
|
||||
return Context.getQualifiedType(baseType, quals);
|
||||
}
|
||||
|
||||
case TYPE_COMPLEX: {
|
||||
if (Record.size() != 1) {
|
||||
Error("Incorrect encoding of complex type");
|
||||
return QualType();
|
||||
}
|
||||
QualType ElemType = Record.readType();
|
||||
return Context.getComplexType(ElemType);
|
||||
auto maybeClass = getTypeClassForCode((TypeCode) Code.get());
|
||||
if (!maybeClass) {
|
||||
Error("Unexpected code for type");
|
||||
return QualType();
|
||||
}
|
||||
|
||||
case TYPE_POINTER: {
|
||||
if (Record.size() != 1) {
|
||||
Error("Incorrect encoding of pointer type");
|
||||
return QualType();
|
||||
}
|
||||
QualType PointeeType = Record.readType();
|
||||
return Context.getPointerType(PointeeType);
|
||||
}
|
||||
|
||||
case TYPE_DECAYED: {
|
||||
if (Record.size() != 1) {
|
||||
Error("Incorrect encoding of decayed type");
|
||||
return QualType();
|
||||
}
|
||||
QualType OriginalType = Record.readType();
|
||||
QualType DT = Context.getAdjustedParameterType(OriginalType);
|
||||
if (!isa<DecayedType>(DT))
|
||||
Error("Decayed type does not decay");
|
||||
return DT;
|
||||
}
|
||||
|
||||
case TYPE_ADJUSTED: {
|
||||
if (Record.size() != 2) {
|
||||
Error("Incorrect encoding of adjusted type");
|
||||
return QualType();
|
||||
}
|
||||
QualType OriginalTy = Record.readType();
|
||||
QualType AdjustedTy = Record.readType();
|
||||
return Context.getAdjustedType(OriginalTy, AdjustedTy);
|
||||
}
|
||||
|
||||
case TYPE_BLOCK_POINTER: {
|
||||
if (Record.size() != 1) {
|
||||
Error("Incorrect encoding of block pointer type");
|
||||
return QualType();
|
||||
}
|
||||
QualType PointeeType = Record.readType();
|
||||
return Context.getBlockPointerType(PointeeType);
|
||||
}
|
||||
|
||||
case TYPE_LVALUE_REFERENCE: {
|
||||
if (Record.size() != 2) {
|
||||
Error("Incorrect encoding of lvalue reference type");
|
||||
return QualType();
|
||||
}
|
||||
QualType PointeeType = Record.readType();
|
||||
return Context.getLValueReferenceType(PointeeType, Record.readBool());
|
||||
}
|
||||
|
||||
case TYPE_RVALUE_REFERENCE: {
|
||||
if (Record.size() != 1) {
|
||||
Error("Incorrect encoding of rvalue reference type");
|
||||
return QualType();
|
||||
}
|
||||
QualType PointeeType = Record.readType();
|
||||
return Context.getRValueReferenceType(PointeeType);
|
||||
}
|
||||
|
||||
case TYPE_MEMBER_POINTER: {
|
||||
if (Record.size() != 2) {
|
||||
Error("Incorrect encoding of member pointer type");
|
||||
return QualType();
|
||||
}
|
||||
QualType PointeeType = Record.readType();
|
||||
QualType ClassType = Record.readType();
|
||||
if (PointeeType.isNull() || ClassType.isNull())
|
||||
return QualType();
|
||||
|
||||
return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
|
||||
}
|
||||
|
||||
case TYPE_CONSTANT_ARRAY: {
|
||||
QualType ElementType = Record.readType();
|
||||
ArrayType::ArraySizeModifier ASM =
|
||||
(ArrayType::ArraySizeModifier) Record.readInt();
|
||||
unsigned IndexTypeQuals = Record.readInt();
|
||||
llvm::APInt Size = Record.readAPInt();
|
||||
Expr *SizeExpr = Record.readExpr();
|
||||
return Context.getConstantArrayType(ElementType, Size, SizeExpr,
|
||||
ASM, IndexTypeQuals);
|
||||
}
|
||||
|
||||
case TYPE_INCOMPLETE_ARRAY: {
|
||||
QualType ElementType = Record.readType();
|
||||
ArrayType::ArraySizeModifier ASM =
|
||||
(ArrayType::ArraySizeModifier) Record.readInt();
|
||||
unsigned IndexTypeQuals = Record.readInt();
|
||||
return Context.getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
|
||||
}
|
||||
|
||||
case TYPE_VARIABLE_ARRAY: {
|
||||
QualType ElementType = Record.readType();
|
||||
ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record.readInt();
|
||||
unsigned IndexTypeQuals = Record.readInt();
|
||||
SourceLocation LBLoc = Record.readSourceLocation();
|
||||
SourceLocation RBLoc = Record.readSourceLocation();
|
||||
return Context.getVariableArrayType(ElementType, ReadExpr(*Loc.F),
|
||||
ASM, IndexTypeQuals,
|
||||
SourceRange(LBLoc, RBLoc));
|
||||
}
|
||||
|
||||
case TYPE_VECTOR: {
|
||||
if (Record.size() != 3) {
|
||||
Error("incorrect encoding of vector type in AST file");
|
||||
return QualType();
|
||||
}
|
||||
|
||||
QualType ElementType = Record.readType();
|
||||
unsigned NumElements = Record.readInt();
|
||||
unsigned VecKind = Record.readInt();
|
||||
return Context.getVectorType(ElementType, NumElements,
|
||||
(VectorType::VectorKind)VecKind);
|
||||
}
|
||||
|
||||
case TYPE_EXT_VECTOR: {
|
||||
if (Record.size() != 3) {
|
||||
Error("incorrect encoding of extended vector type in AST file");
|
||||
return QualType();
|
||||
}
|
||||
|
||||
QualType ElementType = Record.readType();
|
||||
unsigned NumElements = Record.readInt();
|
||||
return Context.getExtVectorType(ElementType, NumElements);
|
||||
}
|
||||
|
||||
case TYPE_FUNCTION_NO_PROTO: {
|
||||
if (Record.size() != 8) {
|
||||
Error("incorrect encoding of no-proto function type");
|
||||
return QualType();
|
||||
}
|
||||
QualType ResultType = Record.readType();
|
||||
FunctionType::ExtInfo Info = readFunctionExtInfo(Record);
|
||||
return Context.getFunctionNoProtoType(ResultType, Info);
|
||||
}
|
||||
|
||||
case TYPE_FUNCTION_PROTO: {
|
||||
QualType ResultType = Record.readType();
|
||||
|
||||
FunctionProtoType::ExtProtoInfo EPI;
|
||||
EPI.ExtInfo = readFunctionExtInfo(Record);
|
||||
EPI.Variadic = Record.readBool();
|
||||
EPI.HasTrailingReturn = Record.readBool();
|
||||
EPI.TypeQuals = Record.readQualifiers();
|
||||
EPI.RefQualifier = static_cast<RefQualifierKind>(Record.readInt());
|
||||
SmallVector<QualType, 8> ExceptionStorage;
|
||||
EPI.ExceptionSpec = Record.readExceptionSpecInfo(ExceptionStorage);
|
||||
|
||||
unsigned NumParams = Record.readInt();
|
||||
SmallVector<QualType, 16> ParamTypes;
|
||||
for (unsigned I = 0; I != NumParams; ++I)
|
||||
ParamTypes.push_back(Record.readType());
|
||||
|
||||
SmallVector<FunctionProtoType::ExtParameterInfo, 4> ExtParameterInfos;
|
||||
if (Record.getIdx() != Record.size()) {
|
||||
for (unsigned I = 0; I != NumParams; ++I)
|
||||
ExtParameterInfos.push_back(
|
||||
FunctionProtoType::ExtParameterInfo
|
||||
::getFromOpaqueValue(Record.readInt()));
|
||||
EPI.ExtParameterInfos = ExtParameterInfos.data();
|
||||
}
|
||||
|
||||
assert(Record.getIdx() == Record.size());
|
||||
|
||||
return Context.getFunctionType(ResultType, ParamTypes, EPI);
|
||||
}
|
||||
|
||||
case TYPE_UNRESOLVED_USING: {
|
||||
return Context.getTypeDeclType(
|
||||
Record.readDeclAs<UnresolvedUsingTypenameDecl>());
|
||||
}
|
||||
|
||||
case TYPE_TYPEDEF: {
|
||||
if (Record.size() != 2) {
|
||||
Error("incorrect encoding of typedef type");
|
||||
return QualType();
|
||||
}
|
||||
TypedefNameDecl *Decl = Record.readDeclAs<TypedefNameDecl>();
|
||||
QualType Canonical = Record.readType();
|
||||
if (!Canonical.isNull())
|
||||
Canonical = Context.getCanonicalType(Canonical);
|
||||
return Context.getTypedefType(Decl, Canonical);
|
||||
}
|
||||
|
||||
case TYPE_TYPEOF_EXPR:
|
||||
return Context.getTypeOfExprType(ReadExpr(*Loc.F));
|
||||
|
||||
case TYPE_TYPEOF: {
|
||||
if (Record.size() != 1) {
|
||||
Error("incorrect encoding of typeof(type) in AST file");
|
||||
return QualType();
|
||||
}
|
||||
QualType UnderlyingType = Record.readType();
|
||||
return Context.getTypeOfType(UnderlyingType);
|
||||
}
|
||||
|
||||
case TYPE_DECLTYPE: {
|
||||
QualType UnderlyingType = Record.readType();
|
||||
return Context.getDecltypeType(Record.readExpr(), UnderlyingType);
|
||||
}
|
||||
|
||||
case TYPE_UNARY_TRANSFORM: {
|
||||
QualType BaseType = Record.readType();
|
||||
QualType UnderlyingType = Record.readType();
|
||||
UnaryTransformType::UTTKind UKind =
|
||||
(UnaryTransformType::UTTKind)Record.readInt();
|
||||
return Context.getUnaryTransformType(BaseType, UnderlyingType, UKind);
|
||||
}
|
||||
|
||||
case TYPE_AUTO: {
|
||||
QualType Deduced = Record.readType();
|
||||
AutoTypeKeyword Keyword = (AutoTypeKeyword) Record.readInt();
|
||||
bool IsDependent = false, IsPack = false;
|
||||
if (Deduced.isNull()) {
|
||||
auto Dependence = Record.readInt();
|
||||
IsDependent = Dependence > 0;
|
||||
IsPack = Dependence > 1;
|
||||
}
|
||||
return Context.getAutoType(Deduced, Keyword, IsDependent, IsPack);
|
||||
}
|
||||
|
||||
case TYPE_DEDUCED_TEMPLATE_SPECIALIZATION: {
|
||||
TemplateName Name = Record.readTemplateName();
|
||||
QualType Deduced = Record.readType();
|
||||
bool IsDependent = Deduced.isNull() ? Record.readBool() : false;
|
||||
return Context.getDeducedTemplateSpecializationType(Name, Deduced,
|
||||
IsDependent);
|
||||
}
|
||||
|
||||
case TYPE_RECORD: {
|
||||
if (Record.size() != 2) {
|
||||
Error("incorrect encoding of record type");
|
||||
return QualType();
|
||||
}
|
||||
bool IsDependent = Record.readBool();
|
||||
RecordDecl *RD = Record.readDeclAs<RecordDecl>();
|
||||
RD = cast<RecordDecl>(RD->getCanonicalDecl());
|
||||
QualType T = Context.getRecordType(RD);
|
||||
const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
|
||||
return T;
|
||||
}
|
||||
|
||||
case TYPE_ENUM: {
|
||||
if (Record.size() != 2) {
|
||||
Error("incorrect encoding of enum type");
|
||||
return QualType();
|
||||
}
|
||||
bool IsDependent = Record.readBool();
|
||||
QualType T = Context.getEnumType(Record.readDeclAs<EnumDecl>());
|
||||
const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
|
||||
return T;
|
||||
}
|
||||
|
||||
case TYPE_ATTRIBUTED: {
|
||||
if (Record.size() != 3) {
|
||||
Error("incorrect encoding of attributed type");
|
||||
return QualType();
|
||||
}
|
||||
QualType modifiedType = Record.readType();
|
||||
QualType equivalentType = Record.readType();
|
||||
AttributedType::Kind kind = static_cast<AttributedType::Kind>(Record.readInt());
|
||||
return Context.getAttributedType(kind, modifiedType, equivalentType);
|
||||
}
|
||||
|
||||
case TYPE_PAREN: {
|
||||
if (Record.size() != 1) {
|
||||
Error("incorrect encoding of paren type");
|
||||
return QualType();
|
||||
}
|
||||
QualType InnerType = Record.readType();
|
||||
return Context.getParenType(InnerType);
|
||||
}
|
||||
|
||||
case TYPE_MACRO_QUALIFIED: {
|
||||
if (Record.size() != 2) {
|
||||
Error("incorrect encoding of macro defined type");
|
||||
return QualType();
|
||||
}
|
||||
QualType UnderlyingTy = Record.readType();
|
||||
IdentifierInfo *MacroII = Record.readIdentifier();
|
||||
return Context.getMacroQualifiedType(UnderlyingTy, MacroII);
|
||||
}
|
||||
|
||||
case TYPE_PACK_EXPANSION: {
|
||||
if (Record.size() != 2) {
|
||||
Error("incorrect encoding of pack expansion type");
|
||||
return QualType();
|
||||
}
|
||||
QualType Pattern = Record.readType();
|
||||
if (Pattern.isNull())
|
||||
return QualType();
|
||||
Optional<unsigned> NumExpansions;
|
||||
unsigned RawNumExpansions = Record.readInt();
|
||||
if (RawNumExpansions)
|
||||
NumExpansions = RawNumExpansions - 1;
|
||||
return Context.getPackExpansionType(Pattern, NumExpansions);
|
||||
}
|
||||
|
||||
case TYPE_ELABORATED: {
|
||||
ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record.readInt();
|
||||
NestedNameSpecifier *NNS = Record.readNestedNameSpecifier();
|
||||
QualType NamedType = Record.readType();
|
||||
TagDecl *OwnedTagDecl = Record.readDeclAs<TagDecl>();
|
||||
return Context.getElaboratedType(Keyword, NNS, NamedType, OwnedTagDecl);
|
||||
}
|
||||
|
||||
case TYPE_OBJC_INTERFACE: {
|
||||
ObjCInterfaceDecl *ItfD = Record.readDeclAs<ObjCInterfaceDecl>();
|
||||
return Context.getObjCInterfaceType(ItfD->getCanonicalDecl());
|
||||
}
|
||||
|
||||
case TYPE_OBJC_TYPE_PARAM: {
|
||||
ObjCTypeParamDecl *Decl = Record.readDeclAs<ObjCTypeParamDecl>();
|
||||
unsigned NumProtos = Record.readInt();
|
||||
SmallVector<ObjCProtocolDecl*, 4> Protos;
|
||||
for (unsigned I = 0; I != NumProtos; ++I)
|
||||
Protos.push_back(Record.readDeclAs<ObjCProtocolDecl>());
|
||||
return Context.getObjCTypeParamType(Decl, Protos);
|
||||
}
|
||||
|
||||
case TYPE_OBJC_OBJECT: {
|
||||
QualType Base = Record.readType();
|
||||
unsigned NumTypeArgs = Record.readInt();
|
||||
SmallVector<QualType, 4> TypeArgs;
|
||||
for (unsigned I = 0; I != NumTypeArgs; ++I)
|
||||
TypeArgs.push_back(Record.readType());
|
||||
unsigned NumProtos = Record.readInt();
|
||||
SmallVector<ObjCProtocolDecl*, 4> Protos;
|
||||
for (unsigned I = 0; I != NumProtos; ++I)
|
||||
Protos.push_back(Record.readDeclAs<ObjCProtocolDecl>());
|
||||
bool IsKindOf = Record.readBool();
|
||||
return Context.getObjCObjectType(Base, TypeArgs, Protos, IsKindOf);
|
||||
}
|
||||
|
||||
case TYPE_OBJC_OBJECT_POINTER: {
|
||||
QualType Pointee = Record.readType();
|
||||
return Context.getObjCObjectPointerType(Pointee);
|
||||
}
|
||||
|
||||
case TYPE_SUBST_TEMPLATE_TYPE_PARM: {
|
||||
QualType Parm = Record.readType();
|
||||
QualType Replacement = Record.readType();
|
||||
return Context.getSubstTemplateTypeParmType(
|
||||
cast<TemplateTypeParmType>(Parm),
|
||||
Context.getCanonicalType(Replacement));
|
||||
}
|
||||
|
||||
case TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK: {
|
||||
QualType Parm = Record.readType();
|
||||
TemplateArgument ArgPack = Record.readTemplateArgument();
|
||||
return Context.getSubstTemplateTypeParmPackType(
|
||||
cast<TemplateTypeParmType>(Parm),
|
||||
ArgPack);
|
||||
}
|
||||
|
||||
case TYPE_INJECTED_CLASS_NAME: {
|
||||
CXXRecordDecl *D = Record.readDeclAs<CXXRecordDecl>();
|
||||
QualType TST = Record.readType(); // probably derivable
|
||||
// FIXME: ASTContext::getInjectedClassNameType is not currently suitable
|
||||
// for AST reading, too much interdependencies.
|
||||
const Type *T = nullptr;
|
||||
for (auto *DI = D; DI; DI = DI->getPreviousDecl()) {
|
||||
if (const Type *Existing = DI->getTypeForDecl()) {
|
||||
T = Existing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!T) {
|
||||
T = new (Context, TypeAlignment) InjectedClassNameType(D, TST);
|
||||
for (auto *DI = D; DI; DI = DI->getPreviousDecl())
|
||||
DI->setTypeForDecl(T);
|
||||
}
|
||||
return QualType(T, 0);
|
||||
}
|
||||
|
||||
case TYPE_TEMPLATE_TYPE_PARM: {
|
||||
unsigned Depth = Record.readInt();
|
||||
unsigned Index = Record.readInt();
|
||||
bool Pack = Record.readBool();
|
||||
auto D = Record.readDeclAs<TemplateTypeParmDecl>();
|
||||
return Context.getTemplateTypeParmType(Depth, Index, Pack, D);
|
||||
}
|
||||
|
||||
case TYPE_DEPENDENT_NAME: {
|
||||
ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record.readInt();
|
||||
NestedNameSpecifier *NNS = Record.readNestedNameSpecifier();
|
||||
const IdentifierInfo *Name = Record.readIdentifier();
|
||||
QualType Canon = Record.readType();
|
||||
if (!Canon.isNull())
|
||||
Canon = Context.getCanonicalType(Canon);
|
||||
return Context.getDependentNameType(Keyword, NNS, Name, Canon);
|
||||
}
|
||||
|
||||
case TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: {
|
||||
ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record.readInt();
|
||||
NestedNameSpecifier *NNS = Record.readNestedNameSpecifier();
|
||||
const IdentifierInfo *Name = Record.readIdentifier();
|
||||
unsigned NumArgs = Record.readInt();
|
||||
SmallVector<TemplateArgument, 8> Args;
|
||||
Args.reserve(NumArgs);
|
||||
while (NumArgs--)
|
||||
Args.push_back(Record.readTemplateArgument());
|
||||
return Context.getDependentTemplateSpecializationType(Keyword, NNS, Name,
|
||||
Args);
|
||||
}
|
||||
|
||||
case TYPE_DEPENDENT_SIZED_ARRAY: {
|
||||
// ArrayType
|
||||
QualType ElementType = Record.readType();
|
||||
ArrayType::ArraySizeModifier ASM
|
||||
= (ArrayType::ArraySizeModifier)Record.readInt();
|
||||
unsigned IndexTypeQuals = Record.readInt();
|
||||
|
||||
// DependentSizedArrayType
|
||||
Expr *NumElts = Record.readExpr();
|
||||
SourceRange Brackets = Record.readSourceRange();
|
||||
|
||||
return Context.getDependentSizedArrayType(ElementType, NumElts, ASM,
|
||||
IndexTypeQuals, Brackets);
|
||||
}
|
||||
|
||||
case TYPE_TEMPLATE_SPECIALIZATION: {
|
||||
bool IsDependent = Record.readBool();
|
||||
TemplateName Name = Record.readTemplateName();
|
||||
SmallVector<TemplateArgument, 8> Args;
|
||||
Record.readTemplateArgumentList(Args);
|
||||
QualType Underlying = Record.readType();
|
||||
QualType T;
|
||||
if (Underlying.isNull())
|
||||
T = Context.getCanonicalTemplateSpecializationType(Name, Args);
|
||||
else
|
||||
T = Context.getTemplateSpecializationType(Name, Args, Underlying);
|
||||
const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
|
||||
return T;
|
||||
}
|
||||
|
||||
case TYPE_ATOMIC: {
|
||||
if (Record.size() != 1) {
|
||||
Error("Incorrect encoding of atomic type");
|
||||
return QualType();
|
||||
}
|
||||
QualType ValueType = Record.readType();
|
||||
return Context.getAtomicType(ValueType);
|
||||
}
|
||||
|
||||
case TYPE_PIPE: {
|
||||
if (Record.size() != 2) {
|
||||
Error("Incorrect encoding of pipe type");
|
||||
return QualType();
|
||||
}
|
||||
|
||||
// Reading the pipe element type.
|
||||
QualType ElementType = Record.readType();
|
||||
unsigned ReadOnly = Record.readInt();
|
||||
return Context.getPipeType(ElementType, ReadOnly);
|
||||
}
|
||||
|
||||
case TYPE_DEPENDENT_SIZED_VECTOR: {
|
||||
QualType ElementType = Record.readType();
|
||||
Expr *SizeExpr = Record.readExpr();
|
||||
SourceLocation AttrLoc = Record.readSourceLocation();
|
||||
unsigned VecKind = Record.readInt();
|
||||
|
||||
return Context.getDependentVectorType(ElementType, SizeExpr, AttrLoc,
|
||||
(VectorType::VectorKind)VecKind);
|
||||
}
|
||||
|
||||
case TYPE_DEPENDENT_SIZED_EXT_VECTOR: {
|
||||
// DependentSizedExtVectorType
|
||||
QualType ElementType = Record.readType();
|
||||
Expr *SizeExpr = Record.readExpr();
|
||||
SourceLocation AttrLoc = Record.readSourceLocation();
|
||||
|
||||
return Context.getDependentSizedExtVectorType(ElementType, SizeExpr,
|
||||
AttrLoc);
|
||||
}
|
||||
|
||||
case TYPE_DEPENDENT_ADDRESS_SPACE: {
|
||||
// DependentAddressSpaceType
|
||||
QualType PointeeType = Record.readType();
|
||||
Expr *AddrSpaceExpr = Record.readExpr();
|
||||
SourceLocation AttrLoc = Record.readSourceLocation();
|
||||
|
||||
return Context.getDependentAddressSpaceType(PointeeType, AddrSpaceExpr,
|
||||
AttrLoc);
|
||||
}
|
||||
}
|
||||
llvm_unreachable("Invalid TypeCode!");
|
||||
}
|
||||
|
||||
FunctionProtoType::ExceptionSpecInfo
|
||||
ASTRecordReader::readExceptionSpecInfo(SmallVectorImpl<QualType> &Exceptions) {
|
||||
FunctionProtoType::ExceptionSpecInfo ESI;
|
||||
ExceptionSpecificationType EST =
|
||||
static_cast<ExceptionSpecificationType>(readInt());
|
||||
ESI.Type = EST;
|
||||
if (EST == EST_Dynamic) {
|
||||
for (unsigned I = 0, N = readInt(); I != N; ++I)
|
||||
Exceptions.push_back(readType());
|
||||
ESI.Exceptions = Exceptions;
|
||||
} else if (isComputedNoexcept(EST)) {
|
||||
ESI.NoexceptExpr = readExpr();
|
||||
} else if (EST == EST_Uninstantiated) {
|
||||
ESI.SourceDecl = readDeclAs<FunctionDecl>();
|
||||
ESI.SourceTemplate = readDeclAs<FunctionDecl>();
|
||||
} else if (EST == EST_Unevaluated) {
|
||||
ESI.SourceDecl = readDeclAs<FunctionDecl>();
|
||||
}
|
||||
return ESI;
|
||||
serialization::AbstractTypeReader<ASTRecordReader> TypeReader(Record);
|
||||
return TypeReader.read(*maybeClass);
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
@ -9075,49 +8559,6 @@ ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const {
|
|||
return LocalID + I->second;
|
||||
}
|
||||
|
||||
DeclarationName ASTRecordReader::readDeclarationName() {
|
||||
ASTContext &Context = getContext();
|
||||
DeclarationName::NameKind Kind = (DeclarationName::NameKind)readInt();
|
||||
switch (Kind) {
|
||||
case DeclarationName::Identifier:
|
||||
return DeclarationName(readIdentifier());
|
||||
|
||||
case DeclarationName::ObjCZeroArgSelector:
|
||||
case DeclarationName::ObjCOneArgSelector:
|
||||
case DeclarationName::ObjCMultiArgSelector:
|
||||
return DeclarationName(readSelector());
|
||||
|
||||
case DeclarationName::CXXConstructorName:
|
||||
return Context.DeclarationNames.getCXXConstructorName(
|
||||
Context.getCanonicalType(readType()));
|
||||
|
||||
case DeclarationName::CXXDestructorName:
|
||||
return Context.DeclarationNames.getCXXDestructorName(
|
||||
Context.getCanonicalType(readType()));
|
||||
|
||||
case DeclarationName::CXXDeductionGuideName:
|
||||
return Context.DeclarationNames.getCXXDeductionGuideName(
|
||||
readDeclAs<TemplateDecl>());
|
||||
|
||||
case DeclarationName::CXXConversionFunctionName:
|
||||
return Context.DeclarationNames.getCXXConversionFunctionName(
|
||||
Context.getCanonicalType(readType()));
|
||||
|
||||
case DeclarationName::CXXOperatorName:
|
||||
return Context.DeclarationNames.getCXXOperatorName(
|
||||
(OverloadedOperatorKind)readInt());
|
||||
|
||||
case DeclarationName::CXXLiteralOperatorName:
|
||||
return Context.DeclarationNames.getCXXLiteralOperatorName(
|
||||
readIdentifier());
|
||||
|
||||
case DeclarationName::CXXUsingDirective:
|
||||
return DeclarationName::getUsingDirectiveName();
|
||||
}
|
||||
|
||||
llvm_unreachable("Invalid NameKind!");
|
||||
}
|
||||
|
||||
DeclarationNameLoc
|
||||
ASTRecordReader::readDeclarationNameLoc(DeclarationName Name) {
|
||||
DeclarationNameLoc DNLoc;
|
||||
|
@ -9171,118 +8612,6 @@ void ASTRecordReader::readQualifierInfo(QualifierInfo &Info) {
|
|||
}
|
||||
}
|
||||
|
||||
TemplateName
|
||||
ASTRecordReader::readTemplateName() {
|
||||
ASTContext &Context = getContext();
|
||||
TemplateName::NameKind Kind = (TemplateName::NameKind)readInt();
|
||||
switch (Kind) {
|
||||
case TemplateName::Template:
|
||||
return TemplateName(readDeclAs<TemplateDecl>());
|
||||
|
||||
case TemplateName::OverloadedTemplate: {
|
||||
unsigned size = readInt();
|
||||
UnresolvedSet<8> Decls;
|
||||
while (size--)
|
||||
Decls.addDecl(readDeclAs<NamedDecl>());
|
||||
|
||||
return Context.getOverloadedTemplateName(Decls.begin(), Decls.end());
|
||||
}
|
||||
|
||||
case TemplateName::AssumedTemplate: {
|
||||
DeclarationName Name = readDeclarationName();
|
||||
return Context.getAssumedTemplateName(Name);
|
||||
}
|
||||
|
||||
case TemplateName::QualifiedTemplate: {
|
||||
NestedNameSpecifier *NNS = readNestedNameSpecifier();
|
||||
bool hasTemplKeyword = readBool();
|
||||
TemplateDecl *Template = readDeclAs<TemplateDecl>();
|
||||
return Context.getQualifiedTemplateName(NNS, hasTemplKeyword, Template);
|
||||
}
|
||||
|
||||
case TemplateName::DependentTemplate: {
|
||||
NestedNameSpecifier *NNS = readNestedNameSpecifier();
|
||||
if (readBool()) // isIdentifier
|
||||
return Context.getDependentTemplateName(NNS, readIdentifier());
|
||||
return Context.getDependentTemplateName(NNS,
|
||||
(OverloadedOperatorKind)readInt());
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParm: {
|
||||
auto *param = readDeclAs<TemplateTemplateParmDecl>();
|
||||
if (!param) return TemplateName();
|
||||
TemplateName replacement = readTemplateName();
|
||||
return Context.getSubstTemplateTemplateParm(param, replacement);
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParmPack: {
|
||||
TemplateTemplateParmDecl *Param
|
||||
= readDeclAs<TemplateTemplateParmDecl>();
|
||||
if (!Param)
|
||||
return TemplateName();
|
||||
|
||||
TemplateArgument ArgPack = readTemplateArgument();
|
||||
if (ArgPack.getKind() != TemplateArgument::Pack)
|
||||
return TemplateName();
|
||||
|
||||
return Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
|
||||
}
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled template name kind!");
|
||||
}
|
||||
|
||||
TemplateArgument ASTRecordReader::readTemplateArgument(bool Canonicalize) {
|
||||
ASTContext &Context = getContext();
|
||||
if (Canonicalize) {
|
||||
// The caller wants a canonical template argument. Sometimes the AST only
|
||||
// wants template arguments in canonical form (particularly as the template
|
||||
// argument lists of template specializations) so ensure we preserve that
|
||||
// canonical form across serialization.
|
||||
TemplateArgument Arg = readTemplateArgument(false);
|
||||
return Context.getCanonicalTemplateArgument(Arg);
|
||||
}
|
||||
|
||||
TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind) readInt();
|
||||
switch (Kind) {
|
||||
case TemplateArgument::Null:
|
||||
return TemplateArgument();
|
||||
case TemplateArgument::Type:
|
||||
return TemplateArgument(readType());
|
||||
case TemplateArgument::Declaration: {
|
||||
ValueDecl *D = readDeclAs<ValueDecl>();
|
||||
return TemplateArgument(D, readType());
|
||||
}
|
||||
case TemplateArgument::NullPtr:
|
||||
return TemplateArgument(readType(), /*isNullPtr*/true);
|
||||
case TemplateArgument::Integral: {
|
||||
llvm::APSInt Value = readAPSInt();
|
||||
QualType T = readType();
|
||||
return TemplateArgument(Context, Value, T);
|
||||
}
|
||||
case TemplateArgument::Template:
|
||||
return TemplateArgument(readTemplateName());
|
||||
case TemplateArgument::TemplateExpansion: {
|
||||
TemplateName Name = readTemplateName();
|
||||
Optional<unsigned> NumTemplateExpansions;
|
||||
if (unsigned NumExpansions = readInt())
|
||||
NumTemplateExpansions = NumExpansions - 1;
|
||||
return TemplateArgument(Name, NumTemplateExpansions);
|
||||
}
|
||||
case TemplateArgument::Expression:
|
||||
return TemplateArgument(readExpr());
|
||||
case TemplateArgument::Pack: {
|
||||
unsigned NumArgs = readInt();
|
||||
TemplateArgument *Args = new (Context) TemplateArgument[NumArgs];
|
||||
for (unsigned I = 0; I != NumArgs; ++I)
|
||||
Args[I] = readTemplateArgument();
|
||||
return TemplateArgument(llvm::makeArrayRef(Args, NumArgs));
|
||||
}
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled template argument kind!");
|
||||
}
|
||||
|
||||
TemplateParameterList *
|
||||
ASTRecordReader::readTemplateParameterList() {
|
||||
SourceLocation TemplateLoc = readSourceLocation();
|
||||
|
@ -9403,67 +8732,13 @@ ASTRecordReader::readCXXCtorInitializers() {
|
|||
return CtorInitializers;
|
||||
}
|
||||
|
||||
NestedNameSpecifier *
|
||||
ASTRecordReader::readNestedNameSpecifier() {
|
||||
ASTContext &Context = getContext();
|
||||
unsigned N = readInt();
|
||||
NestedNameSpecifier *NNS = nullptr, *Prev = nullptr;
|
||||
for (unsigned I = 0; I != N; ++I) {
|
||||
NestedNameSpecifier::SpecifierKind Kind
|
||||
= (NestedNameSpecifier::SpecifierKind)readInt();
|
||||
switch (Kind) {
|
||||
case NestedNameSpecifier::Identifier: {
|
||||
IdentifierInfo *II = readIdentifier();
|
||||
NNS = NestedNameSpecifier::Create(Context, Prev, II);
|
||||
break;
|
||||
}
|
||||
|
||||
case NestedNameSpecifier::Namespace: {
|
||||
NamespaceDecl *NS = readDeclAs<NamespaceDecl>();
|
||||
NNS = NestedNameSpecifier::Create(Context, Prev, NS);
|
||||
break;
|
||||
}
|
||||
|
||||
case NestedNameSpecifier::NamespaceAlias: {
|
||||
NamespaceAliasDecl *Alias = readDeclAs<NamespaceAliasDecl>();
|
||||
NNS = NestedNameSpecifier::Create(Context, Prev, Alias);
|
||||
break;
|
||||
}
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
||||
const Type *T = readType().getTypePtrOrNull();
|
||||
if (!T)
|
||||
return nullptr;
|
||||
|
||||
bool Template = readBool();
|
||||
NNS = NestedNameSpecifier::Create(Context, Prev, Template, T);
|
||||
break;
|
||||
}
|
||||
|
||||
case NestedNameSpecifier::Global:
|
||||
NNS = NestedNameSpecifier::GlobalSpecifier(Context);
|
||||
// No associated value, and there can't be a prefix.
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::Super: {
|
||||
CXXRecordDecl *RD = readDeclAs<CXXRecordDecl>();
|
||||
NNS = NestedNameSpecifier::SuperSpecifier(Context, RD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Prev = NNS;
|
||||
}
|
||||
return NNS;
|
||||
}
|
||||
|
||||
NestedNameSpecifierLoc
|
||||
ASTRecordReader::readNestedNameSpecifierLoc() {
|
||||
ASTContext &Context = getContext();
|
||||
unsigned N = readInt();
|
||||
NestedNameSpecifierLocBuilder Builder;
|
||||
for (unsigned I = 0; I != N; ++I) {
|
||||
auto Kind = (NestedNameSpecifier::SpecifierKind) readInt();
|
||||
auto Kind = readNestedNameSpecifierKind();
|
||||
switch (Kind) {
|
||||
case NestedNameSpecifier::Identifier: {
|
||||
IdentifierInfo *II = readIdentifier();
|
||||
|
@ -9548,7 +8823,7 @@ readAPFloatSemantics(ASTRecordReader &reader) {
|
|||
|
||||
APValue ASTRecordReader::readAPValue() {
|
||||
unsigned Kind = readInt();
|
||||
switch (Kind) {
|
||||
switch ((APValue::ValueKind) Kind) {
|
||||
case APValue::None:
|
||||
return APValue();
|
||||
case APValue::Indeterminate:
|
||||
|
@ -9586,20 +8861,6 @@ APValue ASTRecordReader::readAPValue() {
|
|||
llvm_unreachable("Invalid APValue::ValueKind");
|
||||
}
|
||||
|
||||
/// Read an integral value
|
||||
llvm::APInt ASTRecordReader::readAPInt() {
|
||||
unsigned BitWidth = readInt();
|
||||
unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
|
||||
llvm::APInt Result(BitWidth, NumWords, readIntArray(NumWords).data());
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Read a signed integral value
|
||||
llvm::APSInt ASTRecordReader::readAPSInt() {
|
||||
bool isUnsigned = readBool();
|
||||
return llvm::APSInt(readAPInt(), isUnsigned);
|
||||
}
|
||||
|
||||
/// Read a floating-point value
|
||||
llvm::APFloat ASTRecordReader::readAPFloat(const llvm::fltSemantics &Sem) {
|
||||
return llvm::APFloat(Sem, readAPInt());
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "ASTCommon.h"
|
||||
#include "ASTReaderInternals.h"
|
||||
#include "MultiOnDiskHashTable.h"
|
||||
#include "clang/AST/AbstractTypeWriter.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/ASTUnresolvedSet.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
|
@ -132,458 +133,44 @@ static StringRef bytes(const SmallVectorImpl<T> &v) {
|
|||
// Type serialization
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace clang {
|
||||
|
||||
class ASTTypeWriter {
|
||||
ASTWriter &Writer;
|
||||
ASTRecordWriter Record;
|
||||
|
||||
/// Type code that corresponds to the record generated.
|
||||
TypeCode Code = static_cast<TypeCode>(0);
|
||||
|
||||
/// Abbreviation to use for the record, if any.
|
||||
unsigned AbbrevToUse = 0;
|
||||
|
||||
public:
|
||||
ASTTypeWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record)
|
||||
: Writer(Writer), Record(Writer, Record) {}
|
||||
|
||||
uint64_t Emit() {
|
||||
return Record.Emit(Code, AbbrevToUse);
|
||||
}
|
||||
|
||||
void Visit(QualType T) {
|
||||
if (T.hasLocalNonFastQualifiers()) {
|
||||
Qualifiers Qs = T.getLocalQualifiers();
|
||||
Record.AddTypeRef(T.getLocalUnqualifiedType());
|
||||
Record.push_back(Qs.getAsOpaqueValue());
|
||||
Code = TYPE_EXT_QUAL;
|
||||
AbbrevToUse = Writer.TypeExtQualAbbrev;
|
||||
} else {
|
||||
switch (T->getTypeClass()) {
|
||||
// For all of the concrete, non-dependent types, call the
|
||||
// appropriate visitor function.
|
||||
#define TYPE(Class, Base) \
|
||||
case Type::Class: Visit##Class##Type(cast<Class##Type>(T)); break;
|
||||
#define ABSTRACT_TYPE(Class, Base)
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VisitArrayType(const ArrayType *T);
|
||||
void VisitFunctionType(const FunctionType *T);
|
||||
void VisitTagType(const TagType *T);
|
||||
|
||||
#define TYPE(Class, Base) void Visit##Class##Type(const Class##Type *T);
|
||||
#define ABSTRACT_TYPE(Class, Base)
|
||||
#include "clang/AST/TypeNodes.inc"
|
||||
};
|
||||
|
||||
} // namespace clang
|
||||
|
||||
void ASTTypeWriter::VisitBuiltinType(const BuiltinType *T) {
|
||||
llvm_unreachable("Built-in types are never serialized");
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitComplexType(const ComplexType *T) {
|
||||
Record.AddTypeRef(T->getElementType());
|
||||
Code = TYPE_COMPLEX;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitPointerType(const PointerType *T) {
|
||||
Record.AddTypeRef(T->getPointeeType());
|
||||
Code = TYPE_POINTER;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitDecayedType(const DecayedType *T) {
|
||||
Record.AddTypeRef(T->getOriginalType());
|
||||
Code = TYPE_DECAYED;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitAdjustedType(const AdjustedType *T) {
|
||||
Record.AddTypeRef(T->getOriginalType());
|
||||
Record.AddTypeRef(T->getAdjustedType());
|
||||
Code = TYPE_ADJUSTED;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
|
||||
Record.AddTypeRef(T->getPointeeType());
|
||||
Code = TYPE_BLOCK_POINTER;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
|
||||
Record.AddTypeRef(T->getPointeeTypeAsWritten());
|
||||
Record.push_back(T->isSpelledAsLValue());
|
||||
Code = TYPE_LVALUE_REFERENCE;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
|
||||
Record.AddTypeRef(T->getPointeeTypeAsWritten());
|
||||
Code = TYPE_RVALUE_REFERENCE;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
|
||||
Record.AddTypeRef(T->getPointeeType());
|
||||
Record.AddTypeRef(QualType(T->getClass(), 0));
|
||||
Code = TYPE_MEMBER_POINTER;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitArrayType(const ArrayType *T) {
|
||||
Record.AddTypeRef(T->getElementType());
|
||||
Record.push_back(T->getSizeModifier()); // FIXME: stable values
|
||||
Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
|
||||
VisitArrayType(T);
|
||||
Record.AddAPInt(T->getSize());
|
||||
Record.AddStmt(const_cast<Expr*>(T->getSizeExpr()));
|
||||
Code = TYPE_CONSTANT_ARRAY;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
|
||||
VisitArrayType(T);
|
||||
Code = TYPE_INCOMPLETE_ARRAY;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
|
||||
VisitArrayType(T);
|
||||
Record.AddSourceLocation(T->getLBracketLoc());
|
||||
Record.AddSourceLocation(T->getRBracketLoc());
|
||||
Record.AddStmt(T->getSizeExpr());
|
||||
Code = TYPE_VARIABLE_ARRAY;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitVectorType(const VectorType *T) {
|
||||
Record.AddTypeRef(T->getElementType());
|
||||
Record.push_back(T->getNumElements());
|
||||
Record.push_back(T->getVectorKind());
|
||||
Code = TYPE_VECTOR;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
|
||||
VisitVectorType(T);
|
||||
Code = TYPE_EXT_VECTOR;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitFunctionType(const FunctionType *T) {
|
||||
Record.AddTypeRef(T->getReturnType());
|
||||
FunctionType::ExtInfo C = T->getExtInfo();
|
||||
Record.push_back(C.getNoReturn());
|
||||
Record.push_back(C.getHasRegParm());
|
||||
Record.push_back(C.getRegParm());
|
||||
// FIXME: need to stabilize encoding of calling convention...
|
||||
Record.push_back(C.getCC());
|
||||
Record.push_back(C.getProducesResult());
|
||||
Record.push_back(C.getNoCallerSavedRegs());
|
||||
Record.push_back(C.getNoCfCheck());
|
||||
|
||||
if (C.getHasRegParm() || C.getRegParm() || C.getProducesResult())
|
||||
AbbrevToUse = 0;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
|
||||
VisitFunctionType(T);
|
||||
Code = TYPE_FUNCTION_NO_PROTO;
|
||||
}
|
||||
|
||||
static void addExceptionSpec(const FunctionProtoType *T,
|
||||
ASTRecordWriter &Record) {
|
||||
Record.push_back(T->getExceptionSpecType());
|
||||
if (T->getExceptionSpecType() == EST_Dynamic) {
|
||||
Record.push_back(T->getNumExceptions());
|
||||
for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I)
|
||||
Record.AddTypeRef(T->getExceptionType(I));
|
||||
} else if (isComputedNoexcept(T->getExceptionSpecType())) {
|
||||
Record.AddStmt(T->getNoexceptExpr());
|
||||
} else if (T->getExceptionSpecType() == EST_Uninstantiated) {
|
||||
Record.AddDeclRef(T->getExceptionSpecDecl());
|
||||
Record.AddDeclRef(T->getExceptionSpecTemplate());
|
||||
} else if (T->getExceptionSpecType() == EST_Unevaluated) {
|
||||
Record.AddDeclRef(T->getExceptionSpecDecl());
|
||||
static TypeCode getTypeCodeForTypeClass(Type::TypeClass id) {
|
||||
switch (id) {
|
||||
#define TYPE_BIT_CODE(CLASS_ID, CODE_ID, CODE_VALUE) \
|
||||
case Type::CLASS_ID: return TYPE_##CODE_ID;
|
||||
#include "clang/Serialization/TypeBitCodes.def"
|
||||
case Type::Builtin:
|
||||
llvm_unreachable("shouldn't be serializing a builtin type this way");
|
||||
}
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
|
||||
VisitFunctionType(T);
|
||||
|
||||
Record.push_back(T->isVariadic());
|
||||
Record.push_back(T->hasTrailingReturn());
|
||||
Record.push_back(T->getMethodQuals().getAsOpaqueValue());
|
||||
Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
|
||||
addExceptionSpec(T, Record);
|
||||
|
||||
Record.push_back(T->getNumParams());
|
||||
for (unsigned I = 0, N = T->getNumParams(); I != N; ++I)
|
||||
Record.AddTypeRef(T->getParamType(I));
|
||||
|
||||
if (T->hasExtParameterInfos()) {
|
||||
for (unsigned I = 0, N = T->getNumParams(); I != N; ++I)
|
||||
Record.push_back(T->getExtParameterInfo(I).getOpaqueValue());
|
||||
}
|
||||
|
||||
if (T->isVariadic() || T->hasTrailingReturn() || T->getMethodQuals() ||
|
||||
T->getRefQualifier() || T->getExceptionSpecType() != EST_None ||
|
||||
T->hasExtParameterInfos())
|
||||
AbbrevToUse = 0;
|
||||
|
||||
Code = TYPE_FUNCTION_PROTO;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
|
||||
Record.AddDeclRef(T->getDecl());
|
||||
Code = TYPE_UNRESOLVED_USING;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitTypedefType(const TypedefType *T) {
|
||||
Record.AddDeclRef(T->getDecl());
|
||||
assert(!T->isCanonicalUnqualified() && "Invalid typedef ?");
|
||||
Record.AddTypeRef(T->getCanonicalTypeInternal());
|
||||
Code = TYPE_TYPEDEF;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
|
||||
Record.AddStmt(T->getUnderlyingExpr());
|
||||
Code = TYPE_TYPEOF_EXPR;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitTypeOfType(const TypeOfType *T) {
|
||||
Record.AddTypeRef(T->getUnderlyingType());
|
||||
Code = TYPE_TYPEOF;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitDecltypeType(const DecltypeType *T) {
|
||||
Record.AddTypeRef(T->getUnderlyingType());
|
||||
Record.AddStmt(T->getUnderlyingExpr());
|
||||
Code = TYPE_DECLTYPE;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitUnaryTransformType(const UnaryTransformType *T) {
|
||||
Record.AddTypeRef(T->getBaseType());
|
||||
Record.AddTypeRef(T->getUnderlyingType());
|
||||
Record.push_back(T->getUTTKind());
|
||||
Code = TYPE_UNARY_TRANSFORM;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitAutoType(const AutoType *T) {
|
||||
Record.AddTypeRef(T->getDeducedType());
|
||||
Record.push_back((unsigned)T->getKeyword());
|
||||
if (T->getDeducedType().isNull())
|
||||
Record.push_back(T->containsUnexpandedParameterPack() ? 2 :
|
||||
T->isDependentType() ? 1 : 0);
|
||||
Code = TYPE_AUTO;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitDeducedTemplateSpecializationType(
|
||||
const DeducedTemplateSpecializationType *T) {
|
||||
Record.AddTemplateName(T->getTemplateName());
|
||||
Record.AddTypeRef(T->getDeducedType());
|
||||
if (T->getDeducedType().isNull())
|
||||
Record.push_back(T->isDependentType());
|
||||
Code = TYPE_DEDUCED_TEMPLATE_SPECIALIZATION;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitTagType(const TagType *T) {
|
||||
Record.push_back(T->isDependentType());
|
||||
Record.AddDeclRef(T->getDecl()->getCanonicalDecl());
|
||||
assert(!T->isBeingDefined() &&
|
||||
"Cannot serialize in the middle of a type definition");
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitRecordType(const RecordType *T) {
|
||||
VisitTagType(T);
|
||||
Code = TYPE_RECORD;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitEnumType(const EnumType *T) {
|
||||
VisitTagType(T);
|
||||
Code = TYPE_ENUM;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitAttributedType(const AttributedType *T) {
|
||||
Record.AddTypeRef(T->getModifiedType());
|
||||
Record.AddTypeRef(T->getEquivalentType());
|
||||
Record.push_back(T->getAttrKind());
|
||||
Code = TYPE_ATTRIBUTED;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitSubstTemplateTypeParmType(
|
||||
const SubstTemplateTypeParmType *T) {
|
||||
Record.AddTypeRef(QualType(T->getReplacedParameter(), 0));
|
||||
Record.AddTypeRef(T->getReplacementType());
|
||||
Code = TYPE_SUBST_TEMPLATE_TYPE_PARM;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitSubstTemplateTypeParmPackType(
|
||||
const SubstTemplateTypeParmPackType *T) {
|
||||
Record.AddTypeRef(QualType(T->getReplacedParameter(), 0));
|
||||
Record.AddTemplateArgument(T->getArgumentPack());
|
||||
Code = TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitTemplateSpecializationType(
|
||||
const TemplateSpecializationType *T) {
|
||||
Record.push_back(T->isDependentType());
|
||||
Record.AddTemplateName(T->getTemplateName());
|
||||
Record.push_back(T->getNumArgs());
|
||||
for (const auto &ArgI : *T)
|
||||
Record.AddTemplateArgument(ArgI);
|
||||
Record.AddTypeRef(T->isTypeAlias() ? T->getAliasedType()
|
||||
: T->isCanonicalUnqualified()
|
||||
? QualType()
|
||||
: T->getCanonicalTypeInternal());
|
||||
Code = TYPE_TEMPLATE_SPECIALIZATION;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
|
||||
VisitArrayType(T);
|
||||
Record.AddStmt(T->getSizeExpr());
|
||||
Record.AddSourceRange(T->getBracketsRange());
|
||||
Code = TYPE_DEPENDENT_SIZED_ARRAY;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitDependentSizedExtVectorType(
|
||||
const DependentSizedExtVectorType *T) {
|
||||
Record.AddTypeRef(T->getElementType());
|
||||
Record.AddStmt(T->getSizeExpr());
|
||||
Record.AddSourceLocation(T->getAttributeLoc());
|
||||
Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) {
|
||||
Record.AddTypeRef(T->getElementType());
|
||||
Record.AddStmt(const_cast<Expr*>(T->getSizeExpr()));
|
||||
Record.AddSourceLocation(T->getAttributeLoc());
|
||||
Record.push_back(T->getVectorKind());
|
||||
Code = TYPE_DEPENDENT_SIZED_VECTOR;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitDependentAddressSpaceType(
|
||||
const DependentAddressSpaceType *T) {
|
||||
Record.AddTypeRef(T->getPointeeType());
|
||||
Record.AddStmt(T->getAddrSpaceExpr());
|
||||
Record.AddSourceLocation(T->getAttributeLoc());
|
||||
Code = TYPE_DEPENDENT_ADDRESS_SPACE;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
|
||||
Record.push_back(T->getDepth());
|
||||
Record.push_back(T->getIndex());
|
||||
Record.push_back(T->isParameterPack());
|
||||
Record.AddDeclRef(T->getDecl());
|
||||
Code = TYPE_TEMPLATE_TYPE_PARM;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitDependentNameType(const DependentNameType *T) {
|
||||
Record.push_back(T->getKeyword());
|
||||
Record.AddNestedNameSpecifier(T->getQualifier());
|
||||
Record.AddIdentifierRef(T->getIdentifier());
|
||||
Record.AddTypeRef(
|
||||
T->isCanonicalUnqualified() ? QualType() : T->getCanonicalTypeInternal());
|
||||
Code = TYPE_DEPENDENT_NAME;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitDependentTemplateSpecializationType(
|
||||
const DependentTemplateSpecializationType *T) {
|
||||
Record.push_back(T->getKeyword());
|
||||
Record.AddNestedNameSpecifier(T->getQualifier());
|
||||
Record.AddIdentifierRef(T->getIdentifier());
|
||||
Record.push_back(T->getNumArgs());
|
||||
for (const auto &I : *T)
|
||||
Record.AddTemplateArgument(I);
|
||||
Code = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitPackExpansionType(const PackExpansionType *T) {
|
||||
Record.AddTypeRef(T->getPattern());
|
||||
if (Optional<unsigned> NumExpansions = T->getNumExpansions())
|
||||
Record.push_back(*NumExpansions + 1);
|
||||
else
|
||||
Record.push_back(0);
|
||||
Code = TYPE_PACK_EXPANSION;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitParenType(const ParenType *T) {
|
||||
Record.AddTypeRef(T->getInnerType());
|
||||
Code = TYPE_PAREN;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitMacroQualifiedType(const MacroQualifiedType *T) {
|
||||
Record.AddTypeRef(T->getUnderlyingType());
|
||||
Record.AddIdentifierRef(T->getMacroIdentifier());
|
||||
Code = TYPE_MACRO_QUALIFIED;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
|
||||
Record.push_back(T->getKeyword());
|
||||
Record.AddNestedNameSpecifier(T->getQualifier());
|
||||
Record.AddTypeRef(T->getNamedType());
|
||||
Record.AddDeclRef(T->getOwnedTagDecl());
|
||||
Code = TYPE_ELABORATED;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) {
|
||||
Record.AddDeclRef(T->getDecl()->getCanonicalDecl());
|
||||
Record.AddTypeRef(T->getInjectedSpecializationType());
|
||||
Code = TYPE_INJECTED_CLASS_NAME;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
|
||||
Record.AddDeclRef(T->getDecl()->getCanonicalDecl());
|
||||
Code = TYPE_OBJC_INTERFACE;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitObjCTypeParamType(const ObjCTypeParamType *T) {
|
||||
Record.AddDeclRef(T->getDecl());
|
||||
Record.push_back(T->getNumProtocols());
|
||||
for (const auto *I : T->quals())
|
||||
Record.AddDeclRef(I);
|
||||
Code = TYPE_OBJC_TYPE_PARAM;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
|
||||
Record.AddTypeRef(T->getBaseType());
|
||||
Record.push_back(T->getTypeArgsAsWritten().size());
|
||||
for (auto TypeArg : T->getTypeArgsAsWritten())
|
||||
Record.AddTypeRef(TypeArg);
|
||||
Record.push_back(T->getNumProtocols());
|
||||
for (const auto *I : T->quals())
|
||||
Record.AddDeclRef(I);
|
||||
Record.push_back(T->isKindOfTypeAsWritten());
|
||||
Code = TYPE_OBJC_OBJECT;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
|
||||
Record.AddTypeRef(T->getPointeeType());
|
||||
Code = TYPE_OBJC_OBJECT_POINTER;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitAtomicType(const AtomicType *T) {
|
||||
Record.AddTypeRef(T->getValueType());
|
||||
Code = TYPE_ATOMIC;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitPipeType(const PipeType *T) {
|
||||
Record.AddTypeRef(T->getElementType());
|
||||
Record.push_back(T->isReadOnly());
|
||||
Code = TYPE_PIPE;
|
||||
llvm_unreachable("bad type kind");
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ASTTypeWriter {
|
||||
ASTWriter &Writer;
|
||||
ASTWriter::RecordData Record;
|
||||
ASTRecordWriter BasicWriter;
|
||||
|
||||
public:
|
||||
ASTTypeWriter(ASTWriter &Writer)
|
||||
: Writer(Writer), BasicWriter(Writer, Record) {}
|
||||
|
||||
uint64_t write(QualType T) {
|
||||
if (T.hasLocalNonFastQualifiers()) {
|
||||
Qualifiers Qs = T.getLocalQualifiers();
|
||||
BasicWriter.writeQualType(T.getLocalUnqualifiedType());
|
||||
BasicWriter.writeQualifiers(Qs);
|
||||
return BasicWriter.Emit(TYPE_EXT_QUAL, Writer.getTypeExtQualAbbrev());
|
||||
}
|
||||
|
||||
const Type *typePtr = T.getTypePtr();
|
||||
serialization::AbstractTypeWriter<ASTRecordWriter> atw(BasicWriter);
|
||||
atw.write(typePtr);
|
||||
return BasicWriter.Emit(getTypeCodeForTypeClass(typePtr->getTypeClass()),
|
||||
/*abbrev*/ 0);
|
||||
}
|
||||
};
|
||||
|
||||
class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
|
||||
ASTRecordWriter &Record;
|
||||
|
||||
|
@ -3198,12 +2785,8 @@ void ASTWriter::WriteType(QualType T) {
|
|||
|
||||
assert(Idx.getIndex() >= FirstTypeID && "Re-writing a type from a prior AST");
|
||||
|
||||
RecordData Record;
|
||||
|
||||
// Emit the type's representation.
|
||||
ASTTypeWriter W(*this, Record);
|
||||
W.Visit(T);
|
||||
uint64_t Offset = W.Emit();
|
||||
uint64_t Offset = ASTTypeWriter(*this).write(T);
|
||||
|
||||
// Record the offset for this type.
|
||||
unsigned Index = Idx.getIndex() - FirstTypeID;
|
||||
|
@ -5364,11 +4947,12 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
|
|||
Record.AddStmt(cast<CXXDestructorDecl>(D)->getOperatorDeleteThisArg());
|
||||
break;
|
||||
|
||||
case UPD_CXX_RESOLVED_EXCEPTION_SPEC:
|
||||
addExceptionSpec(
|
||||
cast<FunctionDecl>(D)->getType()->castAs<FunctionProtoType>(),
|
||||
Record);
|
||||
case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
|
||||
auto prototype =
|
||||
cast<FunctionDecl>(D)->getType()->castAs<FunctionProtoType>();
|
||||
Record.writeExceptionSpecInfo(prototype->getExceptionSpecInfo());
|
||||
break;
|
||||
}
|
||||
|
||||
case UPD_CXX_DEDUCED_RETURN_TYPE:
|
||||
Record.push_back(GetOrCreateTypeID(Update.getType()));
|
||||
|
@ -5434,17 +5018,6 @@ void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record) {
|
|||
AddSourceLocation(Range.getEnd(), Record);
|
||||
}
|
||||
|
||||
void ASTRecordWriter::AddAPInt(const llvm::APInt &Value) {
|
||||
Record->push_back(Value.getBitWidth());
|
||||
const uint64_t *Words = Value.getRawData();
|
||||
Record->append(Words, Words + Value.getNumWords());
|
||||
}
|
||||
|
||||
void ASTRecordWriter::AddAPSInt(const llvm::APSInt &Value) {
|
||||
Record->push_back(Value.isUnsigned());
|
||||
AddAPInt(Value);
|
||||
}
|
||||
|
||||
void ASTRecordWriter::AddAPFloat(const llvm::APFloat &Value) {
|
||||
AddAPInt(Value.bitcastToAPInt());
|
||||
}
|
||||
|
@ -5762,44 +5335,6 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) {
|
|||
Decls.insert(I, LocDecl);
|
||||
}
|
||||
|
||||
void ASTRecordWriter::AddDeclarationName(DeclarationName Name) {
|
||||
// FIXME: Emit a stable enum for NameKind. 0 = Identifier etc.
|
||||
Record->push_back(Name.getNameKind());
|
||||
switch (Name.getNameKind()) {
|
||||
case DeclarationName::Identifier:
|
||||
AddIdentifierRef(Name.getAsIdentifierInfo());
|
||||
break;
|
||||
|
||||
case DeclarationName::ObjCZeroArgSelector:
|
||||
case DeclarationName::ObjCOneArgSelector:
|
||||
case DeclarationName::ObjCMultiArgSelector:
|
||||
AddSelectorRef(Name.getObjCSelector());
|
||||
break;
|
||||
|
||||
case DeclarationName::CXXConstructorName:
|
||||
case DeclarationName::CXXDestructorName:
|
||||
case DeclarationName::CXXConversionFunctionName:
|
||||
AddTypeRef(Name.getCXXNameType());
|
||||
break;
|
||||
|
||||
case DeclarationName::CXXDeductionGuideName:
|
||||
AddDeclRef(Name.getCXXDeductionGuideTemplate());
|
||||
break;
|
||||
|
||||
case DeclarationName::CXXOperatorName:
|
||||
Record->push_back(Name.getCXXOverloadedOperator());
|
||||
break;
|
||||
|
||||
case DeclarationName::CXXLiteralOperatorName:
|
||||
AddIdentifierRef(Name.getCXXLiteralIdentifier());
|
||||
break;
|
||||
|
||||
case DeclarationName::CXXUsingDirective:
|
||||
// No extra data to emit
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) {
|
||||
assert(needsAnonymousDeclarationNumber(D) &&
|
||||
"expected an anonymous declaration");
|
||||
|
@ -5866,52 +5401,6 @@ void ASTRecordWriter::AddQualifierInfo(const QualifierInfo &Info) {
|
|||
AddTemplateParameterList(Info.TemplParamLists[i]);
|
||||
}
|
||||
|
||||
void ASTRecordWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS) {
|
||||
// Nested name specifiers usually aren't too long. I think that 8 would
|
||||
// typically accommodate the vast majority.
|
||||
SmallVector<NestedNameSpecifier *, 8> NestedNames;
|
||||
|
||||
// Push each of the NNS's onto a stack for serialization in reverse order.
|
||||
while (NNS) {
|
||||
NestedNames.push_back(NNS);
|
||||
NNS = NNS->getPrefix();
|
||||
}
|
||||
|
||||
Record->push_back(NestedNames.size());
|
||||
while(!NestedNames.empty()) {
|
||||
NNS = NestedNames.pop_back_val();
|
||||
NestedNameSpecifier::SpecifierKind Kind = NNS->getKind();
|
||||
Record->push_back(Kind);
|
||||
switch (Kind) {
|
||||
case NestedNameSpecifier::Identifier:
|
||||
AddIdentifierRef(NNS->getAsIdentifier());
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::Namespace:
|
||||
AddDeclRef(NNS->getAsNamespace());
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::NamespaceAlias:
|
||||
AddDeclRef(NNS->getAsNamespaceAlias());
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
AddTypeRef(QualType(NNS->getAsType(), 0));
|
||||
Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate);
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::Global:
|
||||
// Don't need to write an associated value.
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::Super:
|
||||
AddDeclRef(NNS->getAsRecordDecl());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
|
||||
// Nested name specifiers usually aren't too long. I think that 8 would
|
||||
// typically accommodate the vast majority.
|
||||
|
@ -5966,105 +5455,6 @@ void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
|
|||
}
|
||||
}
|
||||
|
||||
void ASTRecordWriter::AddTemplateName(TemplateName Name) {
|
||||
TemplateName::NameKind Kind = Name.getKind();
|
||||
Record->push_back(Kind);
|
||||
switch (Kind) {
|
||||
case TemplateName::Template:
|
||||
AddDeclRef(Name.getAsTemplateDecl());
|
||||
break;
|
||||
|
||||
case TemplateName::OverloadedTemplate: {
|
||||
OverloadedTemplateStorage *OvT = Name.getAsOverloadedTemplate();
|
||||
Record->push_back(OvT->size());
|
||||
for (const auto &I : *OvT)
|
||||
AddDeclRef(I);
|
||||
break;
|
||||
}
|
||||
|
||||
case TemplateName::AssumedTemplate: {
|
||||
AssumedTemplateStorage *ADLT = Name.getAsAssumedTemplateName();
|
||||
AddDeclarationName(ADLT->getDeclName());
|
||||
break;
|
||||
}
|
||||
|
||||
case TemplateName::QualifiedTemplate: {
|
||||
QualifiedTemplateName *QualT = Name.getAsQualifiedTemplateName();
|
||||
AddNestedNameSpecifier(QualT->getQualifier());
|
||||
Record->push_back(QualT->hasTemplateKeyword());
|
||||
AddDeclRef(QualT->getTemplateDecl());
|
||||
break;
|
||||
}
|
||||
|
||||
case TemplateName::DependentTemplate: {
|
||||
DependentTemplateName *DepT = Name.getAsDependentTemplateName();
|
||||
AddNestedNameSpecifier(DepT->getQualifier());
|
||||
Record->push_back(DepT->isIdentifier());
|
||||
if (DepT->isIdentifier())
|
||||
AddIdentifierRef(DepT->getIdentifier());
|
||||
else
|
||||
Record->push_back(DepT->getOperator());
|
||||
break;
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParm: {
|
||||
SubstTemplateTemplateParmStorage *subst
|
||||
= Name.getAsSubstTemplateTemplateParm();
|
||||
AddDeclRef(subst->getParameter());
|
||||
AddTemplateName(subst->getReplacement());
|
||||
break;
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParmPack: {
|
||||
SubstTemplateTemplateParmPackStorage *SubstPack
|
||||
= Name.getAsSubstTemplateTemplateParmPack();
|
||||
AddDeclRef(SubstPack->getParameterPack());
|
||||
AddTemplateArgument(SubstPack->getArgumentPack());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ASTRecordWriter::AddTemplateArgument(const TemplateArgument &Arg) {
|
||||
Record->push_back(Arg.getKind());
|
||||
switch (Arg.getKind()) {
|
||||
case TemplateArgument::Null:
|
||||
break;
|
||||
case TemplateArgument::Type:
|
||||
AddTypeRef(Arg.getAsType());
|
||||
break;
|
||||
case TemplateArgument::Declaration:
|
||||
AddDeclRef(Arg.getAsDecl());
|
||||
AddTypeRef(Arg.getParamTypeForDecl());
|
||||
break;
|
||||
case TemplateArgument::NullPtr:
|
||||
AddTypeRef(Arg.getNullPtrType());
|
||||
break;
|
||||
case TemplateArgument::Integral:
|
||||
AddAPSInt(Arg.getAsIntegral());
|
||||
AddTypeRef(Arg.getIntegralType());
|
||||
break;
|
||||
case TemplateArgument::Template:
|
||||
AddTemplateName(Arg.getAsTemplateOrTemplatePattern());
|
||||
break;
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
AddTemplateName(Arg.getAsTemplateOrTemplatePattern());
|
||||
if (Optional<unsigned> NumExpansions = Arg.getNumTemplateExpansions())
|
||||
Record->push_back(*NumExpansions + 1);
|
||||
else
|
||||
Record->push_back(0);
|
||||
break;
|
||||
case TemplateArgument::Expression:
|
||||
AddStmt(Arg.getAsExpr());
|
||||
break;
|
||||
case TemplateArgument::Pack:
|
||||
Record->push_back(Arg.pack_size());
|
||||
for (const auto &P : Arg.pack_elements())
|
||||
AddTemplateArgument(P);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ASTRecordWriter::AddTemplateParameterList(
|
||||
const TemplateParameterList *TemplateParams) {
|
||||
assert(TemplateParams && "No TemplateParams!");
|
||||
|
|
|
@ -51,6 +51,8 @@ enum ActionType {
|
|||
GenClangDeclNodes,
|
||||
GenClangStmtNodes,
|
||||
GenClangTypeNodes,
|
||||
GenClangTypeReader,
|
||||
GenClangTypeWriter,
|
||||
GenClangOpcodes,
|
||||
GenClangSACheckers,
|
||||
GenClangCommentHTMLTags,
|
||||
|
@ -145,6 +147,10 @@ cl::opt<ActionType> Action(
|
|||
"Generate Clang AST statement nodes"),
|
||||
clEnumValN(GenClangTypeNodes, "gen-clang-type-nodes",
|
||||
"Generate Clang AST type nodes"),
|
||||
clEnumValN(GenClangTypeReader, "gen-clang-type-reader",
|
||||
"Generate Clang AbstractTypeReader class"),
|
||||
clEnumValN(GenClangTypeWriter, "gen-clang-type-writer",
|
||||
"Generate Clang AbstractTypeWriter class"),
|
||||
clEnumValN(GenClangOpcodes, "gen-clang-opcodes",
|
||||
"Generate Clang constexpr interpreter opcodes"),
|
||||
clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
|
||||
|
@ -282,6 +288,12 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
|||
case GenClangTypeNodes:
|
||||
EmitClangTypeNodes(Records, OS);
|
||||
break;
|
||||
case GenClangTypeReader:
|
||||
EmitClangTypeReader(Records, OS);
|
||||
break;
|
||||
case GenClangTypeWriter:
|
||||
EmitClangTypeWriter(Records, OS);
|
||||
break;
|
||||
case GenClangBasicReader:
|
||||
EmitClangBasicReader(Records, OS);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue