summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ASTContext.h5
-rw-r--r--clang/include/clang/AST/AbstractBasicReader.h368
-rw-r--r--clang/include/clang/AST/AbstractBasicWriter.h335
-rw-r--r--clang/include/clang/AST/AbstractTypeReader.h31
-rw-r--r--clang/include/clang/AST/AbstractTypeWriter.h32
-rw-r--r--clang/include/clang/AST/CMakeLists.txt8
-rw-r--r--clang/include/clang/AST/Type.h10
-rw-r--r--clang/include/clang/AST/TypeProperties.td812
-rw-r--r--clang/include/clang/Serialization/ASTReader.h44
-rw-r--r--clang/include/clang/Serialization/ASTWriter.h58
-rw-r--r--clang/lib/Serialization/ASTReader.cpp779
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp684
-rw-r--r--clang/utils/TableGen/TableGen.cpp12
13 files changed, 1754 insertions, 1424 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 024aa1cb021..4e1d4a44bd8 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -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
diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h
new file mode 100644
index 00000000000..e4e5fe8ba41
--- /dev/null
+++ b/clang/include/clang/AST/AbstractBasicReader.h
@@ -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
diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h
new file mode 100644
index 00000000000..a15a49b046d
--- /dev/null
+++ b/clang/include/clang/AST/AbstractBasicWriter.h
@@ -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
diff --git a/clang/include/clang/AST/AbstractTypeReader.h b/clang/include/clang/AST/AbstractTypeReader.h
new file mode 100644
index 00000000000..9fea7b26f67
--- /dev/null
+++ b/clang/include/clang/AST/AbstractTypeReader.h
@@ -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
diff --git a/clang/include/clang/AST/AbstractTypeWriter.h b/clang/include/clang/AST/AbstractTypeWriter.h
new file mode 100644
index 00000000000..a63cb0be099
--- /dev/null
+++ b/clang/include/clang/AST/AbstractTypeWriter.h
@@ -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
diff --git a/clang/include/clang/AST/CMakeLists.txt b/clang/include/clang/AST/CMakeLists.txt
index 8ba823f07ed..292abe451f7 100644
--- a/clang/include/clang/AST/CMakeLists.txt
+++ b/clang/include/clang/AST/CMakeLists.txt
@@ -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)
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index ab98109eed4..882b5947c9f 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -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;
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
new file mode 100644
index 00000000000..8fa4e4bc1bc
--- /dev/null
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -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);
+ }]>;
+}
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index 3b2b3ab14fb..37c6467b97e 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -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);
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index 76bd874fb01..d465939f1c2 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -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);
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 3fdf451d3d0..c85cfcd3a33 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -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);
- }
-
- case TYPE_COMPLEX: {
- if (Record.size() != 1) {
- Error("Incorrect encoding of complex type");
- return QualType();
- }
- QualType ElemType = Record.readType();
- return Context.getComplexType(ElemType);
- }
-
- 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);
+ if (Code.get() == TYPE_EXT_QUAL) {
+ QualType baseType = Record.readQualType();
+ Qualifiers quals = Record.readQualifiers();
+ return Context.getQualifiedType(baseType, quals);
}
- case TYPE_DEPENDENT_ADDRESS_SPACE: {
- // DependentAddressSpaceType
- QualType PointeeType = Record.readType();
- Expr *AddrSpaceExpr = Record.readExpr();
- SourceLocation AttrLoc = Record.readSourceLocation();
-
- return Context.getDependentAddressSpaceType(PointeeType, AddrSpaceExpr,
- AttrLoc);
- }
+ auto maybeClass = getTypeClassForCode((TypeCode) Code.get());
+ if (!maybeClass) {
+ Error("Unexpected code for type");
+ return QualType();
}
- 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());
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index e3458c48b14..8c39309d263 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -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,457 +133,43 @@ 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");
}
+ llvm_unreachable("bad type kind");
}
-void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
- VisitFunctionType(T);
+namespace {
- 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);
+class ASTTypeWriter {
+ ASTWriter &Writer;
+ ASTWriter::RecordData Record;
+ ASTRecordWriter BasicWriter;
- Record.push_back(T->getNumParams());
- for (unsigned I = 0, N = T->getNumParams(); I != N; ++I)
- Record.AddTypeRef(T->getParamType(I));
+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());
+ }
- if (T->hasExtParameterInfos()) {
- for (unsigned I = 0, N = T->getNumParams(); I != N; ++I)
- Record.push_back(T->getExtParameterInfo(I).getOpaqueValue());
+ const Type *typePtr = T.getTypePtr();
+ serialization::AbstractTypeWriter<ASTRecordWriter> atw(BasicWriter);
+ atw.write(typePtr);
+ return BasicWriter.Emit(getTypeCodeForTypeClass(typePtr->getTypeClass()),
+ /*abbrev*/ 0);
}
-
- 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;
-}
-
-namespace {
+};
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!");
diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index 75e305fe899..6ba90cee4aa 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -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;
OpenPOWER on IntegriCloud