diff options
| -rw-r--r-- | clang/include/clang/AST/ASTContext.h | 5 | ||||
| -rw-r--r-- | clang/include/clang/AST/AbstractBasicReader.h | 368 | ||||
| -rw-r--r-- | clang/include/clang/AST/AbstractBasicWriter.h | 335 | ||||
| -rw-r--r-- | clang/include/clang/AST/AbstractTypeReader.h | 31 | ||||
| -rw-r--r-- | clang/include/clang/AST/AbstractTypeWriter.h | 32 | ||||
| -rw-r--r-- | clang/include/clang/AST/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | clang/include/clang/AST/Type.h | 10 | ||||
| -rw-r--r-- | clang/include/clang/AST/TypeProperties.td | 812 | ||||
| -rw-r--r-- | clang/include/clang/Serialization/ASTReader.h | 44 | ||||
| -rw-r--r-- | clang/include/clang/Serialization/ASTWriter.h | 58 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 779 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 684 | ||||
| -rw-r--r-- | clang/utils/TableGen/TableGen.cpp | 12 |
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; |

