diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -23,6 +23,10 @@ #include "llvm/Support/AlignOf.h" namespace clang { +namespace serialization { +template class BasicReaderBase; +} // end namespace serialization + class AddrLabelExpr; class ASTContext; class CharUnits; @@ -233,12 +237,20 @@ return llvm::hash_value(A.Value); } }; + class LValuePathSerializationHelper { + const void *ElemTy; + + public: + ArrayRef Path; + + LValuePathSerializationHelper(ArrayRef, QualType); + QualType getType(); + }; struct NoLValuePath {}; struct UninitArray {}; struct UninitStruct {}; - friend class ASTRecordReader; - friend class ASTWriter; + template friend class clang::serialization::BasicReaderBase; friend class ASTImporter; friend class ASTNodeImporter; diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h --- a/clang/include/clang/AST/AbstractBasicReader.h +++ b/clang/include/clang/AST/AbstractBasicReader.h @@ -177,6 +177,40 @@ 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 &path) { + auto elemTy = asImpl().readQualType(); + unsigned pathLength = asImpl().readUInt32(); + for (unsigned i = 0; i < pathLength; ++i) { + if (elemTy->template getAs()) { + unsigned int_ = asImpl().readUInt32(); + Decl *decl = asImpl().template readDeclAs(); + if (auto *recordDecl = dyn_cast(decl)) + elemTy = getASTContext().getRecordType(recordDecl); + else + elemTy = cast(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"); diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h --- a/clang/include/clang/AST/AbstractBasicWriter.h +++ b/clang/include/clang/AST/AbstractBasicWriter.h @@ -9,6 +9,7 @@ #ifndef CLANG_AST_ABSTRACTBASICWRITER_H #define CLANG_AST_ABSTRACTBASICWRITER_H +#include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" namespace clang { @@ -121,6 +122,7 @@ class DataStreamBasicWriter : public BasicWriterBase { protected: using BasicWriterBase::asImpl; + DataStreamBasicWriter(ASTContext &ctx) : BasicWriterBase(ctx) {} public: /// Implement property-find by ignoring it. We rely on properties being @@ -163,6 +165,39 @@ 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 path = lvaluePath.Path; + QualType elemTy = lvaluePath.getType(); + asImpl().writeQualType(elemTy); + asImpl().writeUInt32(path.size()); + auto &ctx = ((BasicWriterBase *)this)->getASTContext(); + for (auto elem : path) { + if (elemTy->getAs()) { + asImpl().writeUInt32(elem.getAsBaseOrMember().getInt()); + const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer(); + if (const auto *recordDecl = dyn_cast(baseOrMember)) { + asImpl().writeDeclRef(recordDecl); + elemTy = ctx.getRecordType(recordDecl); + } else { + const auto *valueDecl = cast(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"); diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -72,6 +72,8 @@ 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; @@ -109,7 +111,15 @@ 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">; @@ -237,6 +247,304 @@ string Name = name; } +// Type cases for APValue. +def : PropertyTypeKind; +let Class = PropertyTypeCase in { + def : Creator<[{ return APValue(); }]>; +} +let Class = PropertyTypeCase in { + def : Creator<[{ return APValue::IndeterminateValue(); }]>; +} +let Class = PropertyTypeCase in { + def : Property<"value", APSInt> { + let Read = [{ node.getInt() }]; + } + def : Creator<[{ return APValue(value); }]>; +} +let Class = PropertyTypeCase in { + def : Property<"semantics", UInt32> { + let Read = [{ + static_cast( + 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(semantics)); + return APValue(llvm::APFloat(floatSema, value)); + }]>; +} +let Class = PropertyTypeCase 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 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 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(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(semantics)); + return APValue(llvm::APFloat(sema, real), + llvm::APFloat(sema, imag)); + }]>; +} +let Class = PropertyTypeCase in { + def : ReadHelper<[{ + SmallVector buffer; + unsigned len = node.getVectorLength(); + for (unsigned i = 0; i < len; ++i) + buffer.push_back(node.getVectorElt(i)); + }]>; + def : Property<"elements", Array> { + 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 in { + def : ReadHelper<[{ + SmallVector 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> { + 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 in { + def : ReadHelper<[{ + SmallVector structBases; + unsigned numBases = node.getStructNumBases(); + for (unsigned i = 0; i < numBases; ++i) + structBases.push_back(node.getStructBase(i)); + SmallVector structFields; + unsigned numFields = node.getStructNumFields(); + for (unsigned i = 0; i < numFields; ++i) + structFields.push_back(node.getStructField(i)); + }]>; + def : Property<"bases", Array> { + let Read = [{ structBases }]; + } + def : Property<"fields", Array> { + 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 in { + def : Property<"fieldDecl", DeclRef> { + let Read = [{ node.getUnionField() }]; + } + def : Property<"value", APValue> { + let Read = [{ node.getUnionValue() }]; + } + def : Creator<[{ + return APValue(cast(fieldDecl), std::move(value)); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"lhs", StmtRef> { + let Read = [{ const_cast(node.getAddrLabelDiffLHS()) }]; + } + def : Property<"rhs", StmtRef> { + let Read = [{ const_cast(node.getAddrLabelDiffRHS()) }]; + } + def : Creator<[{ + return APValue(cast(lhs), cast(rhs)); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"isDerived", Bool> { + let Read = [{ node.isMemberPointerToDerivedMember() }]; + } + def : Property<"member", ValueDeclRef> { + let Read = [{ node.getMemberPointerDecl() }]; + } + def : Property<"memberPath", Array> { + 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 in { + def : ReadHelper<[{ + auto lvalueBase = node.getLValueBase(); + const Expr *expr = + lvalueBase ? lvalueBase.dyn_cast() : nullptr; + bool lvalueBaseIsExpr = (bool) expr; + bool lvalueBaseIsTypeInfo = lvalueBase.is(); + QualType elemTy; + if (lvalueBase) { + if (lvalueBaseIsTypeInfo) { + elemTy = lvalueBase.getTypeInfoType(); + } else if (lvalueBaseIsExpr) { + elemTy = expr->getType(); + } else { + elemTy = lvalueBase.get()->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(lvalueBase) }]; + } + def : Property<"isNullPtr", Bool> { + let Read = [{ node.isNullPointer() }]; + } + def : Property<"typeInfo", QualType> { + let Conditional = [{ hasBase && isTypeInfo }]; + let Read = [{ + QualType(node.getLValueBase().get().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) }]; + } + def : Property<"decl", DeclRef> { + let Conditional = [{ hasBase && !isTypeInfo && !isExpr }]; + let Read = [{ lvalueBase.get() }]; + } + 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(stmt.getValue()), + callIndex.getValue(), version.getValue()); + elemTy = base.get()->getType(); + } else { + base = APValue::LValueBase(cast(decl.getValue()), + callIndex.getValue(), version.getValue()); + elemTy = base.get()->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; diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h --- a/clang/include/clang/Serialization/ASTRecordReader.h +++ b/clang/include/clang/Serialization/ASTRecordReader.h @@ -281,7 +281,7 @@ } /// Read an arbitrary constant value, advancing Idx. - APValue readAPValue(); + // APValue readAPValue(); (inherited) /// Read an integral value, advancing Idx. // llvm::APInt readAPInt(); (inherited) diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h --- a/clang/include/clang/Serialization/ASTRecordWriter.h +++ b/clang/include/clang/Serialization/ASTRecordWriter.h @@ -55,13 +55,14 @@ 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; @@ -165,7 +166,7 @@ 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) { diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -555,6 +555,11 @@ 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 diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -154,6 +154,14 @@ ID.AddInteger(Value); } +APValue::LValuePathSerializationHelper::LValuePathSerializationHelper( + ArrayRef Path, QualType ElemTy) + : ElemTy((const void *)ElemTy.getTypePtrOrNull()), Path(Path) {} + +QualType APValue::LValuePathSerializationHelper::getType() { + return QualType::getFromOpaquePtr(ElemTy); +} + namespace { struct LVBase { APValue::LValueBase Base; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -8941,165 +8941,6 @@ return SourceRange(beg, end); } -static llvm::FixedPointSemantics -ReadFixedPointSemantics(const SmallVectorImpl &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(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(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(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(); - APValue Value = asImpl().readAPValue(); - return APValue(FDecl, std::move(Value)); - } - case APValue::AddrLabelDiff: { - auto *LHS = cast(asImpl().readExpr()); - auto *RHS = cast(asImpl().readExpr()); - return APValue(LHS, RHS); - } - case APValue::MemberPointer: { - APValue Result; - bool IsDerived = asImpl().readUInt32(); - auto *Member = asImpl().readDeclAs(); - unsigned PathSize = asImpl().readUInt32(); - const CXXRecordDecl **PathArray = - Result.setMemberPointerUninit(Member, IsDerived, PathSize).data(); - for (unsigned LoopIdx = 0; LoopIdx < PathSize; LoopIdx++) - PathArray[LoopIdx] = - asImpl().readDeclAs()->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()->getType(); - } else { - Base = APValue::LValueBase(asImpl().readDeclAs(), - CallIndex, Version); - ElemTy = Base.get()->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()) { - unsigned Int = asImpl().readUInt32(); - Decl *D = asImpl().readDeclAs(); - if (auto *RD = dyn_cast(D)) - ElemTy = getASTContext().getRecordType(RD); - else - ElemTy = cast(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()); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5121,144 +5121,6 @@ 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(Kind)); - switch (Kind) { - case APValue::None: - case APValue::Indeterminate: - return; - case APValue::Int: - AddAPSInt(Value.getInt()); - return; - case APValue::Float: - push_back(static_cast( - 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(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(Value.getAddrLabelDiffLHS())); - AddStmt(const_cast(Value.getAddrLabelDiffRHS())); - return; - case APValue::MemberPointer: { - push_back(Value.isMemberPointerToDerivedMember()); - AddDeclRef(Value.getMemberPointerDecl()); - ArrayRef 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() << 2 | - Value.getLValueBase().is() << 3 | - Value.isNullPointer() << 4 | - static_cast(Value.getLValueBase()) << 5); - QualType ElemTy; - if (Value.getLValueBase()) { - assert(!Value.getLValueBase().is() && - "in C++20 dynamic allocation are transient so they shouldn't " - "appear in the AST"); - if (!Value.getLValueBase().is()) { - push_back(Value.getLValueBase().getCallIndex()); - push_back(Value.getLValueBase().getVersion()); - if (const auto *E = Value.getLValueBase().dyn_cast()) { - AddStmt(const_cast(E)); - ElemTy = E->getType(); - } else { - AddDeclRef(Value.getLValueBase().get()); - ElemTy = Value.getLValueBase().get()->getType(); - } - } else { - AddTypeRef( - QualType(Value.getLValueBase().get().getType(), 0)); - AddTypeRef(Value.getLValueBase().getTypeInfoType()); - ElemTy = Value.getLValueBase().getTypeInfoType(); - } - } - push_back(Value.getLValueOffset().getQuantity()); - push_back(Value.getLValuePath().size()); - if (Value.hasLValuePath()) { - ArrayRef Path = Value.getLValuePath(); - for (auto Elem : Path) { - if (ElemTy->getAs()) { - push_back(Elem.getAsBaseOrMember().getInt()); - const Decl *BaseOrMember = Elem.getAsBaseOrMember().getPointer(); - if (const auto *RD = dyn_cast(BaseOrMember)) { - AddDeclRef(RD); - ElemTy = Writer->Context->getRecordType(RD); - } else { - const auto *VD = cast(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)); } diff --git a/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp b/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp --- a/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp +++ b/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp @@ -708,15 +708,13 @@ // Emit the Basic{Reader,Writer}Base template. Out << "template \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(*this); }\n"; auto enterReaderWriterMethod = [&](StringRef cxxTypeName,