#include "llvm/Support/AlignOf.h"
namespace clang {
+namespace serialization {
+template <typename T> class BasicReaderBase;
+} // end namespace serialization
+
class AddrLabelExpr;
class ASTContext;
class CharUnits;
return llvm::hash_value(A.Value);
}
};
+ class LValuePathSerializationHelper {
+ const void *ElemTy;
+
+ public:
+ ArrayRef<LValuePathEntry> Path;
+
+ LValuePathSerializationHelper(ArrayRef<LValuePathEntry>, QualType);
+ QualType getType();
+ };
struct NoLValuePath {};
struct UninitArray {};
struct UninitStruct {};
- friend class ASTRecordReader;
- friend class ASTWriter;
+ template <typename Impl> friend class clang::serialization::BasicReaderBase;
friend class ASTImporter;
friend class ASTNodeImporter;
return llvm::APInt(bitWidth, numWords, &data[0]);
}
+ llvm::FixedPointSemantics readFixedPointSemantics() {
+ unsigned width = asImpl().readUInt32();
+ unsigned scale = asImpl().readUInt32();
+ unsigned tmp = asImpl().readUInt32();
+ bool isSigned = tmp & 0x1;
+ bool isSaturated = tmp & 0x2;
+ bool hasUnsignedPadding = tmp & 0x4;
+ return llvm::FixedPointSemantics(width, scale, isSigned, isSaturated,
+ hasUnsignedPadding);
+ }
+
+ APValue::LValuePathSerializationHelper readLValuePathSerializationHelper(
+ SmallVectorImpl<APValue::LValuePathEntry> &path) {
+ auto elemTy = asImpl().readQualType();
+ unsigned pathLength = asImpl().readUInt32();
+ for (unsigned i = 0; i < pathLength; ++i) {
+ if (elemTy->template getAs<RecordType>()) {
+ unsigned int_ = asImpl().readUInt32();
+ Decl *decl = asImpl().template readDeclAs<Decl>();
+ if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))
+ elemTy = getASTContext().getRecordType(recordDecl);
+ else
+ elemTy = cast<ValueDecl>(decl)->getType();
+ path.push_back(
+ APValue::LValuePathEntry(APValue::BaseOrMemberType(decl, int_)));
+ } else {
+ elemTy = getASTContext().getAsArrayType(elemTy)->getElementType();
+ path.push_back(
+ APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()));
+ }
+ }
+ return APValue::LValuePathSerializationHelper(path, elemTy);
+ }
+
Qualifiers readQualifiers() {
static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),
"update this if the value size changes");
#ifndef CLANG_AST_ABSTRACTBASICWRITER_H
#define CLANG_AST_ABSTRACTBASICWRITER_H
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
namespace clang {
class DataStreamBasicWriter : public BasicWriterBase<Impl> {
protected:
using BasicWriterBase<Impl>::asImpl;
+ DataStreamBasicWriter(ASTContext &ctx) : BasicWriterBase<Impl>(ctx) {}
public:
/// Implement property-find by ignoring it. We rely on properties being
asImpl().writeUInt64(words[i]);
}
+ void writeFixedPointSemantics(const llvm::FixedPointSemantics &sema) {
+ asImpl().writeUInt32(sema.getWidth());
+ asImpl().writeUInt32(sema.getScale());
+ asImpl().writeUInt32(sema.isSigned() | sema.isSaturated() << 1 |
+ sema.hasUnsignedPadding() << 2);
+ }
+
+ void writeLValuePathSerializationHelper(
+ APValue::LValuePathSerializationHelper lvaluePath) {
+ ArrayRef<APValue::LValuePathEntry> path = lvaluePath.Path;
+ QualType elemTy = lvaluePath.getType();
+ asImpl().writeQualType(elemTy);
+ asImpl().writeUInt32(path.size());
+ auto &ctx = ((BasicWriterBase<Impl> *)this)->getASTContext();
+ for (auto elem : path) {
+ if (elemTy->getAs<RecordType>()) {
+ asImpl().writeUInt32(elem.getAsBaseOrMember().getInt());
+ const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer();
+ if (const auto *recordDecl = dyn_cast<CXXRecordDecl>(baseOrMember)) {
+ asImpl().writeDeclRef(recordDecl);
+ elemTy = ctx.getRecordType(recordDecl);
+ } else {
+ const auto *valueDecl = cast<ValueDecl>(baseOrMember);
+ asImpl().writeDeclRef(valueDecl);
+ elemTy = valueDecl->getType();
+ }
+ } else {
+ asImpl().writeUInt32(elem.getAsArrayIndex());
+ elemTy = ctx.getAsArrayType(elemTy)->getElementType();
+ }
+ }
+ }
+
void writeQualifiers(Qualifiers value) {
static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t),
"update this if the value size changes");
def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; }
def APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; }
+def APValue : PropertyType { let PassByReference = 1; }
+def APValueKind : EnumPropertyType<"APValue::ValueKind">;
def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">;
def AttrKind : EnumPropertyType<"attr::Kind">;
def AutoTypeKeyword : EnumPropertyType;
SubclassPropertyType<"ValueDecl", DeclRef>;
def ElaboratedTypeKeyword : EnumPropertyType;
def ExtParameterInfo : PropertyType<"FunctionProtoType::ExtParameterInfo">;
+def FixedPointSemantics : PropertyType<"llvm::FixedPointSemantics"> {
+ let PassByReference = 1;
+}
def Identifier : RefPropertyType<"IdentifierInfo"> { let ConstWhenWriting = 1; }
+def LValuePathEntry : PropertyType<"APValue::LValuePathEntry">;
+def LValuePathSerializationHelper :
+ PropertyType<"APValue::LValuePathSerializationHelper"> {
+ let BufferElementTypes = [ LValuePathEntry ];
+}
def NestedNameSpecifier : PropertyType<"NestedNameSpecifier *">;
def NestedNameSpecifierKind :
EnumPropertyType<"NestedNameSpecifier::SpecifierKind">;
string Name = name;
}
+// Type cases for APValue.
+def : PropertyTypeKind<APValue, APValueKind,
+ "node.getKind()">;
+let Class = PropertyTypeCase<APValue, "None"> in {
+ def : Creator<[{ return APValue(); }]>;
+}
+let Class = PropertyTypeCase<APValue, "Indeterminate"> in {
+ def : Creator<[{ return APValue::IndeterminateValue(); }]>;
+}
+let Class = PropertyTypeCase<APValue, "Int"> in {
+ def : Property<"value", APSInt> {
+ let Read = [{ node.getInt() }];
+ }
+ def : Creator<[{ return APValue(value); }]>;
+}
+let Class = PropertyTypeCase<APValue, "Float"> in {
+ def : Property<"semantics", UInt32> {
+ let Read = [{
+ static_cast<uint32_t>(
+ llvm::APFloatBase::SemanticsToEnum(node.getFloat().getSemantics()))
+ }];
+ }
+ def : Property<"value", APInt> {
+ let Read = [{ node.getFloat().bitcastToAPInt() }];
+ }
+ def : Creator<[{
+ const llvm::fltSemantics &floatSema = llvm::APFloatBase::EnumToSemantics(
+ static_cast<llvm::APFloatBase::Semantics>(semantics));
+ return APValue(llvm::APFloat(floatSema, value));
+ }]>;
+}
+let Class = PropertyTypeCase<APValue, "FixedPoint"> in {
+ def : Property<"semantics", FixedPointSemantics> {
+ let Read = [{ node.getFixedPoint().getSemantics() }];
+ }
+ def : Property<"value", APSInt> {
+ let Read = [{ node.getFixedPoint().getValue() }];
+ }
+ def : Creator<[{
+ return APValue(llvm::APFixedPoint(std::move(value), semantics));
+ }]>;
+}
+let Class = PropertyTypeCase<APValue, "ComplexInt"> in {
+ def : Property<"real", APSInt> {
+ let Read = [{ node.getComplexIntReal() }];
+ }
+ def : Property<"imag", APSInt> {
+ let Read = [{ node.getComplexIntImag() }];
+ }
+ def : Creator<[{ return APValue(real, imag); }]>;
+}
+let Class = PropertyTypeCase<APValue, "ComplexFloat"> in {
+ def : ReadHelper<[{
+ auto sema = llvm::APFloatBase::SemanticsToEnum(
+ node.getComplexFloatReal().getSemantics());
+ assert(sema == llvm::APFloatBase::SemanticsToEnum(
+ node.getComplexFloatImag().getSemantics()));
+ }]>;
+ def : Property<"semantics", UInt32> {
+ let Read = [{ static_cast<uint32_t>(sema) }];
+ }
+ def : Property<"real", APInt> {
+ let Read = [{ node.getComplexFloatReal().bitcastToAPInt() }];
+ }
+ def : Property<"imag", APInt> {
+ let Read = [{ node.getComplexFloatImag().bitcastToAPInt() }];
+ }
+ def : Creator<[{
+ const llvm::fltSemantics &sema = llvm::APFloatBase::EnumToSemantics(
+ static_cast<llvm::APFloatBase::Semantics>(semantics));
+ return APValue(llvm::APFloat(sema, real),
+ llvm::APFloat(sema, imag));
+ }]>;
+}
+let Class = PropertyTypeCase<APValue, "Vector"> in {
+ def : ReadHelper<[{
+ SmallVector<APValue, 4> buffer;
+ unsigned len = node.getVectorLength();
+ for (unsigned i = 0; i < len; ++i)
+ buffer.push_back(node.getVectorElt(i));
+ }]>;
+ def : Property<"elements", Array<APValue>> {
+ let Read = [{ buffer }];
+ }
+ def : Creator<[{
+ APValue result;
+ result.MakeVector();
+ unsigned length = elements.size();
+ (void)result.setVectorUninit(length);
+ for (unsigned i = 0; i < length; i++)
+ result.getVectorElt(i) = elements[i];
+ return result;
+ }]>;
+}
+let Class = PropertyTypeCase<APValue, "Array"> in {
+ def : ReadHelper<[{
+ SmallVector<APValue, 4> buffer{};
+ unsigned initLength = node.getArrayInitializedElts();
+ for (unsigned i = 0; i < initLength; ++i)
+ buffer.push_back(node.getArrayInitializedElt(i));
+ if (node.hasArrayFiller())
+ buffer.push_back(node.getArrayFiller());
+ }]>;
+ def : Property<"totalLength", UInt32> {
+ let Read = [{ node.getArraySize() }];
+ }
+ def : Property<"hasFiller", Bool> {
+ let Read = [{ node.hasArrayFiller() }];
+ }
+ def : Property<"elements", Array<APValue>> {
+ let Read = [{ buffer }];
+ }
+ def : Creator<[{
+ APValue result;
+ unsigned initLength = elements.size() - (hasFiller ? 1 : 0);
+ result.MakeArray(initLength, totalLength);
+ for (unsigned i = 0; i < initLength; ++i)
+ result.getArrayInitializedElt(i) = elements[i];
+ if (hasFiller)
+ result.getArrayFiller() = elements.back();
+ return result;
+ }]>;
+}
+let Class = PropertyTypeCase<APValue, "Struct"> in {
+ def : ReadHelper<[{
+ SmallVector<APValue, 4> structBases;
+ unsigned numBases = node.getStructNumBases();
+ for (unsigned i = 0; i < numBases; ++i)
+ structBases.push_back(node.getStructBase(i));
+ SmallVector<APValue, 4> structFields;
+ unsigned numFields = node.getStructNumFields();
+ for (unsigned i = 0; i < numFields; ++i)
+ structFields.push_back(node.getStructField(i));
+ }]>;
+ def : Property<"bases", Array<APValue>> {
+ let Read = [{ structBases }];
+ }
+ def : Property<"fields", Array<APValue>> {
+ let Read = [{ structFields }];
+ }
+ def : Creator<[{
+ APValue result;
+ result.MakeStruct(bases.size(), fields.size());
+ for (unsigned i = 0; i < bases.size(); ++i)
+ result.getStructBase(i) = bases[i];
+ for (unsigned i = 0; i < fields.size(); ++i)
+ result.getStructField(i) = fields[i];
+ return result;
+ }]>;
+}
+let Class = PropertyTypeCase<APValue, "Union"> in {
+ def : Property<"fieldDecl", DeclRef> {
+ let Read = [{ node.getUnionField() }];
+ }
+ def : Property<"value", APValue> {
+ let Read = [{ node.getUnionValue() }];
+ }
+ def : Creator<[{
+ return APValue(cast<clang::FieldDecl>(fieldDecl), std::move(value));
+ }]>;
+}
+let Class = PropertyTypeCase<APValue, "AddrLabelDiff"> in {
+ def : Property<"lhs", StmtRef> {
+ let Read = [{ const_cast<AddrLabelExpr *>(node.getAddrLabelDiffLHS()) }];
+ }
+ def : Property<"rhs", StmtRef> {
+ let Read = [{ const_cast<AddrLabelExpr *>(node.getAddrLabelDiffRHS()) }];
+ }
+ def : Creator<[{
+ return APValue(cast<AddrLabelExpr>(lhs), cast<AddrLabelExpr>(rhs));
+ }]>;
+}
+let Class = PropertyTypeCase<APValue, "MemberPointer"> in {
+ def : Property<"isDerived", Bool> {
+ let Read = [{ node.isMemberPointerToDerivedMember() }];
+ }
+ def : Property<"member", ValueDeclRef> {
+ let Read = [{ node.getMemberPointerDecl() }];
+ }
+ def : Property<"memberPath", Array<CXXRecordDeclRef>> {
+ let Read = [{ node.getMemberPointerPath() }];
+ }
+ def : Creator<[{
+ APValue result;
+ unsigned pathSize = memberPath.size();
+ const CXXRecordDecl **pathArray =
+ result.setMemberPointerUninit(member, isDerived, pathSize).data();
+ for (unsigned i = 0; i < pathSize; ++i)
+ pathArray[i] = memberPath[i]->getCanonicalDecl();
+ return result;
+ }]>;
+}
+let Class = PropertyTypeCase<APValue, "LValue"> in {
+ def : ReadHelper<[{
+ auto lvalueBase = node.getLValueBase();
+ const Expr *expr =
+ lvalueBase ? lvalueBase.dyn_cast<const Expr *>() : nullptr;
+ bool lvalueBaseIsExpr = (bool) expr;
+ bool lvalueBaseIsTypeInfo = lvalueBase.is<TypeInfoLValue>();
+ QualType elemTy;
+ if (lvalueBase) {
+ if (lvalueBaseIsTypeInfo) {
+ elemTy = lvalueBase.getTypeInfoType();
+ } else if (lvalueBaseIsExpr) {
+ elemTy = expr->getType();
+ } else {
+ elemTy = lvalueBase.get<const ValueDecl *>()->getType();
+ }
+ }
+ }]>;
+ def : Property<"hasLValuePath", Bool> {
+ let Read = [{ node.hasLValuePath() }];
+ }
+ def : Property<"isLValueOnePastTheEnd", Bool> {
+ let Read = [{ node.isLValueOnePastTheEnd() }];
+ }
+ def : Property<"isExpr", Bool> {
+ let Read = [{ lvalueBaseIsExpr }];
+ }
+ def : Property<"isTypeInfo", Bool> {
+ let Read = [{ lvalueBaseIsTypeInfo }];
+ }
+ def : Property<"hasBase", Bool> {
+ let Read = [{ static_cast<bool>(lvalueBase) }];
+ }
+ def : Property<"isNullPtr", Bool> {
+ let Read = [{ node.isNullPointer() }];
+ }
+ def : Property<"typeInfo", QualType> {
+ let Conditional = [{ hasBase && isTypeInfo }];
+ let Read = [{
+ QualType(node.getLValueBase().get<TypeInfoLValue>().getType(), 0)
+ }];
+ }
+ def : Property<"type", QualType> {
+ let Conditional = [{ hasBase && isTypeInfo }];
+ let Read = [{ node.getLValueBase().getTypeInfoType() }];
+ }
+ def : Property<"callIndex", UInt32> {
+ let Conditional = [{ hasBase && !isTypeInfo }];
+ let Read = [{ node.getLValueBase().getCallIndex() }];
+ }
+ def : Property<"version", UInt32> {
+ let Conditional = [{ hasBase && !isTypeInfo }];
+ let Read = [{ node.getLValueBase().getVersion() }];
+ }
+ def : Property<"stmt", StmtRef> {
+ let Conditional = [{ hasBase && !isTypeInfo && isExpr }];
+ let Read = [{ const_cast<Expr *>(expr) }];
+ }
+ def : Property<"decl", DeclRef> {
+ let Conditional = [{ hasBase && !isTypeInfo && !isExpr }];
+ let Read = [{ lvalueBase.get<const ValueDecl *>() }];
+ }
+ def : Property<"offsetQuantity", UInt32> {
+ let Read = [{ node.getLValueOffset().getQuantity() }];
+ }
+ def : Property<"lvaluePath", LValuePathSerializationHelper> {
+ let Conditional = [{ hasLValuePath }];
+ let Read = [{
+ APValue::LValuePathSerializationHelper(node.getLValuePath(), elemTy)
+ }];
+ }
+ def : Creator<[{
+ (void)ctx;
+ APValue::LValueBase base;
+ QualType elemTy;
+ if (hasBase) {
+ if (isTypeInfo) {
+ base = APValue::LValueBase::getTypeInfo(
+ TypeInfoLValue(typeInfo.getValue().getTypePtr()), type.getValue());
+ elemTy = base.getTypeInfoType();
+ } else if (isExpr) {
+ base = APValue::LValueBase(cast<Expr>(stmt.getValue()),
+ callIndex.getValue(), version.getValue());
+ elemTy = base.get<const Expr *>()->getType();
+ } else {
+ base = APValue::LValueBase(cast<ValueDecl>(decl.getValue()),
+ callIndex.getValue(), version.getValue());
+ elemTy = base.get<const ValueDecl *>()->getType();
+ }
+ }
+ CharUnits offset = CharUnits::fromQuantity(offsetQuantity);
+ APValue result;
+ result.MakeLValue();
+ if (!hasLValuePath) {
+ result.setLValue(base, offset, APValue::NoLValuePath{}, isNullPtr);
+ return result;
+ }
+ auto pathLength = lvaluePath->Path.size();
+ APValue::LValuePathEntry *path = result.setLValueUninit(
+ base, offset, pathLength, isLValueOnePastTheEnd, isNullPtr).data();
+ assert(lvaluePath->getType() == elemTy && "Unexpected type reference!");
+ llvm::copy(lvaluePath->Path, path);
+ return result;
+ }]>;
+}
+
// Type cases for DeclarationName.
def : PropertyTypeKind<DeclarationName, DeclarationNameKind,
"node.getNameKind()">;
}
/// Read an arbitrary constant value, advancing Idx.
- APValue readAPValue();
+ // APValue readAPValue(); (inherited)
/// Read an integral value, advancing Idx.
// llvm::APInt readAPInt(); (inherited)
public:
/// Construct a ASTRecordWriter that uses the default encoding scheme.
- ASTRecordWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record)
- : Writer(&Writer), Record(&Record) {}
+ ASTRecordWriter(ASTWriter &W, ASTWriter::RecordDataImpl &Record)
+ : DataStreamBasicWriter(W.getASTContext()), Writer(&W), Record(&Record) {}
/// Construct a ASTRecordWriter that uses the same encoding scheme as another
/// ASTRecordWriter.
ASTRecordWriter(ASTRecordWriter &Parent, ASTWriter::RecordDataImpl &Record)
- : Writer(Parent.Writer), Record(&Record) {}
+ : DataStreamBasicWriter(Parent.getASTContext()), Writer(Parent.Writer),
+ Record(&Record) {}
/// Copying an ASTRecordWriter is almost certainly a bug.
ASTRecordWriter(const ASTRecordWriter &) = delete;
void AddAPFloat(const llvm::APFloat &Value);
/// Emit an APvalue.
- void AddAPValue(const APValue &Value);
+ void AddAPValue(const APValue &Value) { writeAPValue(Value); }
/// Emit a reference to an identifier.
void AddIdentifierRef(const IdentifierInfo *II) {
bool IncludeTimestamps = true);
~ASTWriter() override;
+ ASTContext &getASTContext() const {
+ assert(Context && "requested AST context when not writing AST");
+ return *Context;
+ }
+
const LangOptions &getLangOpts() const;
/// Get a timestamp for output into the AST file. The actual timestamp
ID.AddInteger(Value);
}
+APValue::LValuePathSerializationHelper::LValuePathSerializationHelper(
+ ArrayRef<LValuePathEntry> Path, QualType ElemTy)
+ : ElemTy((const void *)ElemTy.getTypePtrOrNull()), Path(Path) {}
+
+QualType APValue::LValuePathSerializationHelper::getType() {
+ return QualType::getFromOpaquePtr(ElemTy);
+}
+
namespace {
struct LVBase {
APValue::LValueBase Base;
return SourceRange(beg, end);
}
-static llvm::FixedPointSemantics
-ReadFixedPointSemantics(const SmallVectorImpl<uint64_t> &Record,
- unsigned &Idx) {
- unsigned Width = Record[Idx++];
- unsigned Scale = Record[Idx++];
- uint64_t Tmp = Record[Idx++];
- bool IsSigned = Tmp & 0x1;
- bool IsSaturated = Tmp & 0x2;
- bool HasUnsignedPadding = Tmp & 0x4;
- return llvm::FixedPointSemantics(Width, Scale, IsSigned, IsSaturated,
- HasUnsignedPadding);
-}
-
-APValue ASTRecordReader::readAPValue() {
- auto Kind = static_cast<APValue::ValueKind>(asImpl().readUInt32());
- switch (Kind) {
- case APValue::None:
- return APValue();
- case APValue::Indeterminate:
- return APValue::IndeterminateValue();
- case APValue::Int:
- return APValue(asImpl().readAPSInt());
- case APValue::Float: {
- const llvm::fltSemantics &FloatSema = llvm::APFloatBase::EnumToSemantics(
- static_cast<llvm::APFloatBase::Semantics>(asImpl().readUInt32()));
- return APValue(asImpl().readAPFloat(FloatSema));
- }
- case APValue::FixedPoint: {
- llvm::FixedPointSemantics FPSema = ReadFixedPointSemantics(Record, Idx);
- return APValue(llvm::APFixedPoint(readAPInt(), FPSema));
- }
- case APValue::ComplexInt: {
- llvm::APSInt First = asImpl().readAPSInt();
- return APValue(std::move(First), asImpl().readAPSInt());
- }
- case APValue::ComplexFloat: {
- const llvm::fltSemantics &FloatSema = llvm::APFloatBase::EnumToSemantics(
- static_cast<llvm::APFloatBase::Semantics>(asImpl().readUInt32()));
- llvm::APFloat First = readAPFloat(FloatSema);
- return APValue(std::move(First), asImpl().readAPFloat(FloatSema));
- }
- case APValue::Vector: {
- APValue Result;
- Result.MakeVector();
- unsigned Length = asImpl().readUInt32();
- (void)Result.setVectorUninit(Length);
- for (unsigned LoopIdx = 0; LoopIdx < Length; LoopIdx++)
- Result.getVectorElt(LoopIdx) = asImpl().readAPValue();
- return Result;
- }
- case APValue::Array: {
- APValue Result;
- unsigned InitLength = asImpl().readUInt32();
- unsigned TotalLength = asImpl().readUInt32();
- Result.MakeArray(InitLength, TotalLength);
- for (unsigned LoopIdx = 0; LoopIdx < InitLength; LoopIdx++)
- Result.getArrayInitializedElt(LoopIdx) = asImpl().readAPValue();
- if (Result.hasArrayFiller())
- Result.getArrayFiller() = asImpl().readAPValue();
- return Result;
- }
- case APValue::Struct: {
- APValue Result;
- unsigned BasesLength = asImpl().readUInt32();
- unsigned FieldsLength = asImpl().readUInt32();
- Result.MakeStruct(BasesLength, FieldsLength);
- for (unsigned LoopIdx = 0; LoopIdx < BasesLength; LoopIdx++)
- Result.getStructBase(LoopIdx) = asImpl().readAPValue();
- for (unsigned LoopIdx = 0; LoopIdx < FieldsLength; LoopIdx++)
- Result.getStructField(LoopIdx) = asImpl().readAPValue();
- return Result;
- }
- case APValue::Union: {
- auto *FDecl = asImpl().readDeclAs<FieldDecl>();
- APValue Value = asImpl().readAPValue();
- return APValue(FDecl, std::move(Value));
- }
- case APValue::AddrLabelDiff: {
- auto *LHS = cast<AddrLabelExpr>(asImpl().readExpr());
- auto *RHS = cast<AddrLabelExpr>(asImpl().readExpr());
- return APValue(LHS, RHS);
- }
- case APValue::MemberPointer: {
- APValue Result;
- bool IsDerived = asImpl().readUInt32();
- auto *Member = asImpl().readDeclAs<ValueDecl>();
- unsigned PathSize = asImpl().readUInt32();
- const CXXRecordDecl **PathArray =
- Result.setMemberPointerUninit(Member, IsDerived, PathSize).data();
- for (unsigned LoopIdx = 0; LoopIdx < PathSize; LoopIdx++)
- PathArray[LoopIdx] =
- asImpl().readDeclAs<const CXXRecordDecl>()->getCanonicalDecl();
- return Result;
- }
- case APValue::LValue: {
- uint64_t Bits = asImpl().readUInt32();
- bool HasLValuePath = Bits & 0x1;
- bool IsLValueOnePastTheEnd = Bits & 0x2;
- bool IsExpr = Bits & 0x4;
- bool IsTypeInfo = Bits & 0x8;
- bool IsNullPtr = Bits & 0x10;
- bool HasBase = Bits & 0x20;
- APValue::LValueBase Base;
- QualType ElemTy;
- assert((!IsExpr || !IsTypeInfo) && "LValueBase cannot be both");
- if (HasBase) {
- if (!IsTypeInfo) {
- unsigned CallIndex = asImpl().readUInt32();
- unsigned Version = asImpl().readUInt32();
- if (IsExpr) {
- Base = APValue::LValueBase(asImpl().readExpr(), CallIndex, Version);
- ElemTy = Base.get<const Expr *>()->getType();
- } else {
- Base = APValue::LValueBase(asImpl().readDeclAs<const ValueDecl>(),
- CallIndex, Version);
- ElemTy = Base.get<const ValueDecl *>()->getType();
- }
- } else {
- QualType TypeInfo = asImpl().readType();
- QualType Type = asImpl().readType();
- Base = APValue::LValueBase::getTypeInfo(
- TypeInfoLValue(TypeInfo.getTypePtr()), Type);
- Base.getTypeInfoType();
- }
- }
- CharUnits Offset = CharUnits::fromQuantity(asImpl().readUInt32());
- unsigned PathLength = asImpl().readUInt32();
- APValue Result;
- Result.MakeLValue();
- if (HasLValuePath) {
- APValue::LValuePathEntry *Path =
- Result
- .setLValueUninit(Base, Offset, PathLength, IsLValueOnePastTheEnd,
- IsNullPtr)
- .data();
- for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) {
- if (ElemTy->getAs<RecordType>()) {
- unsigned Int = asImpl().readUInt32();
- Decl *D = asImpl().readDeclAs<Decl>();
- if (auto *RD = dyn_cast<CXXRecordDecl>(D))
- ElemTy = getASTContext().getRecordType(RD);
- else
- ElemTy = cast<ValueDecl>(D)->getType();
- Path[LoopIdx] =
- APValue::LValuePathEntry(APValue::BaseOrMemberType(D, Int));
- } else {
- ElemTy = getASTContext().getAsArrayType(ElemTy)->getElementType();
- Path[LoopIdx] =
- APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32());
- }
- }
- } else
- Result.setLValue(Base, Offset, APValue::NoLValuePath{}, IsNullPtr);
- return Result;
- }
- }
- llvm_unreachable("Invalid APValue::ValueKind");
-}
-
/// Read a floating-point value
llvm::APFloat ASTRecordReader::readAPFloat(const llvm::fltSemantics &Sem) {
return llvm::APFloat(Sem, readAPInt());
AddAPInt(Value.bitcastToAPInt());
}
-static void WriteFixedPointSemantics(ASTRecordWriter &Record,
- llvm::FixedPointSemantics FPSema) {
- Record.push_back(FPSema.getWidth());
- Record.push_back(FPSema.getScale());
- Record.push_back(FPSema.isSigned() | FPSema.isSaturated() << 1 |
- FPSema.hasUnsignedPadding() << 2);
-}
-
-void ASTRecordWriter::AddAPValue(const APValue &Value) {
- APValue::ValueKind Kind = Value.getKind();
- push_back(static_cast<uint64_t>(Kind));
- switch (Kind) {
- case APValue::None:
- case APValue::Indeterminate:
- return;
- case APValue::Int:
- AddAPSInt(Value.getInt());
- return;
- case APValue::Float:
- push_back(static_cast<uint64_t>(
- llvm::APFloatBase::SemanticsToEnum(Value.getFloat().getSemantics())));
- AddAPFloat(Value.getFloat());
- return;
- case APValue::FixedPoint: {
- WriteFixedPointSemantics(*this, Value.getFixedPoint().getSemantics());
- AddAPSInt(Value.getFixedPoint().getValue());
- return;
- }
- case APValue::ComplexInt: {
- AddAPSInt(Value.getComplexIntReal());
- AddAPSInt(Value.getComplexIntImag());
- return;
- }
- case APValue::ComplexFloat: {
- assert(llvm::APFloatBase::SemanticsToEnum(
- Value.getComplexFloatImag().getSemantics()) ==
- llvm::APFloatBase::SemanticsToEnum(
- Value.getComplexFloatReal().getSemantics()));
- push_back(static_cast<uint64_t>(llvm::APFloatBase::SemanticsToEnum(
- Value.getComplexFloatReal().getSemantics())));
- AddAPFloat(Value.getComplexFloatReal());
- AddAPFloat(Value.getComplexFloatImag());
- return;
- }
- case APValue::Vector:
- push_back(Value.getVectorLength());
- for (unsigned Idx = 0; Idx < Value.getVectorLength(); Idx++)
- AddAPValue(Value.getVectorElt(Idx));
- return;
- case APValue::Array:
- push_back(Value.getArrayInitializedElts());
- push_back(Value.getArraySize());
- for (unsigned Idx = 0; Idx < Value.getArrayInitializedElts(); Idx++)
- AddAPValue(Value.getArrayInitializedElt(Idx));
- if (Value.hasArrayFiller())
- AddAPValue(Value.getArrayFiller());
- return;
- case APValue::Struct:
- push_back(Value.getStructNumBases());
- push_back(Value.getStructNumFields());
- for (unsigned Idx = 0; Idx < Value.getStructNumBases(); Idx++)
- AddAPValue(Value.getStructBase(Idx));
- for (unsigned Idx = 0; Idx < Value.getStructNumFields(); Idx++)
- AddAPValue(Value.getStructField(Idx));
- return;
- case APValue::Union:
- AddDeclRef(Value.getUnionField());
- AddAPValue(Value.getUnionValue());
- return;
- case APValue::AddrLabelDiff:
- AddStmt(const_cast<AddrLabelExpr *>(Value.getAddrLabelDiffLHS()));
- AddStmt(const_cast<AddrLabelExpr *>(Value.getAddrLabelDiffRHS()));
- return;
- case APValue::MemberPointer: {
- push_back(Value.isMemberPointerToDerivedMember());
- AddDeclRef(Value.getMemberPointerDecl());
- ArrayRef<const CXXRecordDecl *> RecordPath = Value.getMemberPointerPath();
- push_back(RecordPath.size());
- for (auto Elem : RecordPath)
- AddDeclRef(Elem);
- return;
- }
- case APValue::LValue: {
- push_back(Value.hasLValuePath() | Value.isLValueOnePastTheEnd() << 1 |
- Value.getLValueBase().is<const Expr *>() << 2 |
- Value.getLValueBase().is<TypeInfoLValue>() << 3 |
- Value.isNullPointer() << 4 |
- static_cast<bool>(Value.getLValueBase()) << 5);
- QualType ElemTy;
- if (Value.getLValueBase()) {
- assert(!Value.getLValueBase().is<DynamicAllocLValue>() &&
- "in C++20 dynamic allocation are transient so they shouldn't "
- "appear in the AST");
- if (!Value.getLValueBase().is<TypeInfoLValue>()) {
- push_back(Value.getLValueBase().getCallIndex());
- push_back(Value.getLValueBase().getVersion());
- if (const auto *E = Value.getLValueBase().dyn_cast<const Expr *>()) {
- AddStmt(const_cast<Expr *>(E));
- ElemTy = E->getType();
- } else {
- AddDeclRef(Value.getLValueBase().get<const ValueDecl *>());
- ElemTy = Value.getLValueBase().get<const ValueDecl *>()->getType();
- }
- } else {
- AddTypeRef(
- QualType(Value.getLValueBase().get<TypeInfoLValue>().getType(), 0));
- AddTypeRef(Value.getLValueBase().getTypeInfoType());
- ElemTy = Value.getLValueBase().getTypeInfoType();
- }
- }
- push_back(Value.getLValueOffset().getQuantity());
- push_back(Value.getLValuePath().size());
- if (Value.hasLValuePath()) {
- ArrayRef<APValue::LValuePathEntry> Path = Value.getLValuePath();
- for (auto Elem : Path) {
- if (ElemTy->getAs<RecordType>()) {
- push_back(Elem.getAsBaseOrMember().getInt());
- const Decl *BaseOrMember = Elem.getAsBaseOrMember().getPointer();
- if (const auto *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
- AddDeclRef(RD);
- ElemTy = Writer->Context->getRecordType(RD);
- } else {
- const auto *VD = cast<ValueDecl>(BaseOrMember);
- AddDeclRef(VD);
- ElemTy = VD->getType();
- }
- } else {
- push_back(Elem.getAsArrayIndex());
- ElemTy = Writer->Context->getAsArrayType(ElemTy)->getElementType();
- }
- }
- }
- }
- return;
- }
- llvm_unreachable("Invalid APValue::ValueKind");
-}
-
void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) {
Record.push_back(getIdentifierRef(II));
}
// Emit the Basic{Reader,Writer}Base template.
Out << "template <class Impl>\n"
"class Basic" << info.ClassSuffix << "Base {\n";
- if (info.IsReader)
- Out << " ASTContext &C;\n";
+ Out << " ASTContext &C;\n";
Out << "protected:\n"
- " Basic" << info.ClassSuffix << "Base"
- << (info.IsReader ? "(ASTContext &ctx) : C(ctx)" : "()")
- << " {}\n"
+ " Basic"
+ << info.ClassSuffix << "Base" << ("(ASTContext &ctx) : C(ctx)")
+ << " {}\n"
"public:\n";
- if (info.IsReader)
- Out << " ASTContext &getASTContext() { return C; }\n";
+ Out << " ASTContext &getASTContext() { return C; }\n";
Out << " Impl &asImpl() { return static_cast<Impl&>(*this); }\n";
auto enterReaderWriterMethod = [&](StringRef cxxTypeName,