diff options
author | Tyker <tyker1@outlook.com> | 2020-10-01 17:58:07 +0200 |
---|---|---|
committer | Tyker <tyker1@outlook.com> | 2020-10-21 19:03:13 +0200 |
commit | cf34dd0c4e84b69bb901f9cd4f3491852238ec44 (patch) | |
tree | 374f9f672a18ddc70ca83abf8c0354fe2c4afda7 /clang/lib | |
parent | 8b7dac81d378c339d3e55f6f51cd0c42803903ad (diff) | |
download | llvm-cf34dd0c4e84b69bb901f9cd4f3491852238ec44.zip llvm-cf34dd0c4e84b69bb901f9cd4f3491852238ec44.tar.gz llvm-cf34dd0c4e84b69bb901f9cd4f3491852238ec44.tar.bz2 |
[clang] Improve Serialization/Imporing/Dumping of APValues
Changes:
- initializer expressions of constexpr variable are now wraped in a ConstantExpr. this is mainly used for testing purposes. the old caching system has not yet been removed.
- Add all the missing Serialization and Importing for APValue.
- Improve dumping of APValue when ASTContext isn't available.
- Cleanup leftover from last patch.
- Add Tests for Import and serialization.
Differential Revision: https://reviews.llvm.org/D63640
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/APValue.cpp | 43 | ||||
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 3 | ||||
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 183 | ||||
-rw-r--r-- | clang/lib/AST/Expr.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 152 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 91 |
6 files changed, 419 insertions, 56 deletions
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 8d402ee..919cd86 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -882,17 +882,26 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, LVal.IsNullPtr = IsNullPtr; } -void APValue::setLValue(LValueBase B, const CharUnits &O, - ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, - bool IsNullPtr) { +MutableArrayRef<APValue::LValuePathEntry> +APValue::setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size, + bool IsOnePastTheEnd, bool IsNullPtr) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data.buffer); + LV &LVal = *((LV *)(char *)Data.buffer); LVal.Base = B; LVal.IsOnePastTheEnd = IsOnePastTheEnd; LVal.Offset = O; - LVal.resizePath(Path.size()); - memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); LVal.IsNullPtr = IsNullPtr; + LVal.resizePath(Size); + return {LVal.getPath(), Size}; +} + +void APValue::setLValue(LValueBase B, const CharUnits &O, + ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, + bool IsNullPtr) { + MutableArrayRef<APValue::LValuePathEntry> InternalPath = + setLValueUninit(B, O, Path.size(), IsOnePastTheEnd, IsNullPtr); + memcpy(InternalPath.data(), Path.data(), + Path.size() * sizeof(LValuePathEntry)); } const ValueDecl *APValue::getMemberPointerDecl() const { @@ -929,15 +938,27 @@ void APValue::MakeArray(unsigned InitElts, unsigned Size) { Kind = Array; } -void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef<const CXXRecordDecl*> Path) { +MutableArrayRef<APValue::LValuePathEntry> +setLValueUninit(APValue::LValueBase B, const CharUnits &O, unsigned Size, + bool OnePastTheEnd, bool IsNullPtr); + +MutableArrayRef<const CXXRecordDecl *> +APValue::setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember, + unsigned Size) { assert(isAbsent() && "Bad state change"); - MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; + MemberPointerData *MPD = new ((void *)(char *)Data.buffer) MemberPointerData; Kind = MemberPointer; MPD->MemberAndIsDerivedMember.setPointer( Member ? cast<ValueDecl>(Member->getCanonicalDecl()) : nullptr); MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); - MPD->resizePath(Path.size()); + MPD->resizePath(Size); + return {MPD->getPath(), MPD->PathLength}; +} + +void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef<const CXXRecordDecl *> Path) { + MutableArrayRef<const CXXRecordDecl *> InternalPath = + setMemberPointerUninit(Member, IsDerivedMember, Path.size()); for (unsigned I = 0; I != Path.size(); ++I) - MPD->getPath()[I] = Path[I]->getCanonicalDecl(); + InternalPath[I] = Path[I]->getCanonicalDecl(); } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index bddaaa6..32bb3f9 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1005,9 +1005,6 @@ ASTContext::~ASTContext() { for (const auto &Value : ModuleInitializers) Value.second->~PerModuleInitializers(); - - for (APValue *Value : APValueCleanups) - Value->~APValue(); } void ASTContext::setTraversalScope(const std::vector<Decl *> &TopLevelDecls) { diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 5a70d0ee..23720bf 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -397,6 +397,7 @@ namespace clang { Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); Expected<CXXCastPath> ImportCastPath(CastExpr *E); + Expected<APValue> ImportAPValue(const APValue &FromValue); using Designator = DesignatedInitExpr::Designator; @@ -6692,18 +6693,11 @@ ExpectedStmt ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) { Error Err = Error::success(); auto ToSubExpr = importChecked(Err, E->getSubExpr()); + auto ToResult = importChecked(Err, E->getAPValueResult()); if (Err) return std::move(Err); - // TODO : Handle APValue::ValueKind that require importing. - - APValue::ValueKind Kind = E->getResultAPValueKind(); - if (Kind == APValue::Int || Kind == APValue::Float || - Kind == APValue::FixedPoint || Kind == APValue::ComplexFloat || - Kind == APValue::ComplexInt) - return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, - E->getAPValueResult()); - return ConstantExpr::Create(Importer.getToContext(), ToSubExpr); + return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, ToResult); } ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Error Err = Error::success(); @@ -8804,6 +8798,11 @@ ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { return Imported; } +llvm::Expected<APValue> ASTImporter::Import(const APValue &FromValue) { + ASTNodeImporter Importer(*this); + return Importer.ImportAPValue(FromValue); +} + Error ASTImporter::ImportDefinition(Decl *From) { ExpectedDecl ToOrErr = Import(From); if (!ToOrErr) @@ -8934,6 +8933,172 @@ Expected<Selector> ASTImporter::Import(Selector FromSel) { return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data()); } +llvm::Expected<APValue> +ASTNodeImporter::ImportAPValue(const APValue &FromValue) { + APValue Result; + llvm::Error Err = llvm::Error::success(); + auto ImportLoop = [&](const APValue *From, APValue *To, unsigned Size) { + for (unsigned Idx = 0; Idx < Size; Idx++) { + APValue Tmp = importChecked(Err, From[Idx]); + To[Idx] = Tmp; + } + }; + switch (FromValue.getKind()) { + case APValue::None: + case APValue::Indeterminate: + case APValue::Int: + case APValue::Float: + case APValue::FixedPoint: + case APValue::ComplexInt: + case APValue::ComplexFloat: + Result = FromValue; + break; + case APValue::Vector: { + Result.MakeVector(); + MutableArrayRef<APValue> Elts = + Result.setVectorUninit(FromValue.getVectorLength()); + ImportLoop( + ((const APValue::Vec *)(const char *)FromValue.Data.buffer)->Elts, + Elts.data(), FromValue.getVectorLength()); + break; + } + case APValue::Array: + Result.MakeArray(FromValue.getArrayInitializedElts(), + FromValue.getArraySize()); + ImportLoop( + ((const APValue::Arr *)(const char *)FromValue.Data.buffer)->Elts, + ((const APValue::Arr *)(const char *)Result.Data.buffer)->Elts, + FromValue.getArrayInitializedElts()); + break; + case APValue::Struct: + Result.MakeStruct(FromValue.getStructNumBases(), + FromValue.getStructNumFields()); + ImportLoop( + ((const APValue::StructData *)(const char *)FromValue.Data.buffer) + ->Elts, + ((const APValue::StructData *)(const char *)Result.Data.buffer)->Elts, + FromValue.getStructNumBases() + FromValue.getStructNumFields()); + break; + case APValue::Union: { + Result.MakeUnion(); + const Decl *ImpFDecl = importChecked(Err, FromValue.getUnionField()); + APValue ImpValue = importChecked(Err, FromValue.getUnionValue()); + if (Err) + return std::move(Err); + Result.setUnion(cast<FieldDecl>(ImpFDecl), ImpValue); + break; + } + case APValue::AddrLabelDiff: { + Result.MakeAddrLabelDiff(); + const Expr *ImpLHS = importChecked(Err, FromValue.getAddrLabelDiffLHS()); + const Expr *ImpRHS = importChecked(Err, FromValue.getAddrLabelDiffRHS()); + if (Err) + return std::move(Err); + Result.setAddrLabelDiff(cast<AddrLabelExpr>(ImpLHS), + cast<AddrLabelExpr>(ImpRHS)); + break; + } + case APValue::MemberPointer: { + const Decl *ImpMemPtrDecl = + importChecked(Err, FromValue.getMemberPointerDecl()); + if (Err) + return std::move(Err); + MutableArrayRef<const CXXRecordDecl *> ToPath = + Result.setMemberPointerUninit( + cast<const ValueDecl>(ImpMemPtrDecl), + FromValue.isMemberPointerToDerivedMember(), + FromValue.getMemberPointerPath().size()); + llvm::ArrayRef<const CXXRecordDecl *> FromPath = + Result.getMemberPointerPath(); + for (unsigned Idx = 0; Idx < FromValue.getMemberPointerPath().size(); + Idx++) { + const Decl *ImpDecl = importChecked(Err, FromPath[Idx]); + if (Err) + return std::move(Err); + ToPath[Idx] = cast<const CXXRecordDecl>(ImpDecl->getCanonicalDecl()); + } + break; + } + case APValue::LValue: + APValue::LValueBase Base; + QualType FromElemTy; + if (FromValue.getLValueBase()) { + assert(!FromValue.getLValueBase().is<DynamicAllocLValue>() && + "in C++20 dynamic allocation are transient so they shouldn't " + "appear in the AST"); + if (!FromValue.getLValueBase().is<TypeInfoLValue>()) { + if (const auto *E = + FromValue.getLValueBase().dyn_cast<const Expr *>()) { + FromElemTy = E->getType(); + const Expr *ImpExpr = importChecked(Err, E); + if (Err) + return std::move(Err); + Base = APValue::LValueBase(ImpExpr, + FromValue.getLValueBase().getCallIndex(), + FromValue.getLValueBase().getVersion()); + } else { + FromElemTy = + FromValue.getLValueBase().get<const ValueDecl *>()->getType(); + const Decl *ImpDecl = importChecked( + Err, FromValue.getLValueBase().get<const ValueDecl *>()); + if (Err) + return std::move(Err); + Base = APValue::LValueBase(cast<ValueDecl>(ImpDecl), + FromValue.getLValueBase().getCallIndex(), + FromValue.getLValueBase().getVersion()); + } + } else { + FromElemTy = FromValue.getLValueBase().getTypeInfoType(); + QualType ImpTypeInfo = importChecked( + Err, + QualType(FromValue.getLValueBase().get<TypeInfoLValue>().getType(), + 0)); + QualType ImpType = + importChecked(Err, FromValue.getLValueBase().getTypeInfoType()); + if (Err) + return std::move(Err); + Base = APValue::LValueBase::getTypeInfo( + TypeInfoLValue(ImpTypeInfo.getTypePtr()), ImpType); + } + } + CharUnits Offset = FromValue.getLValueOffset(); + unsigned PathLength = FromValue.getLValuePath().size(); + Result.MakeLValue(); + if (FromValue.hasLValuePath()) { + MutableArrayRef<APValue::LValuePathEntry> ToPath = Result.setLValueUninit( + Base, Offset, PathLength, FromValue.isLValueOnePastTheEnd(), + FromValue.isNullPointer()); + llvm::ArrayRef<APValue::LValuePathEntry> FromPath = + FromValue.getLValuePath(); + for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) { + if (FromElemTy->isRecordType()) { + const Decl *FromDecl = + FromPath[LoopIdx].getAsBaseOrMember().getPointer(); + const Decl *ImpDecl = importChecked(Err, FromDecl); + if (Err) + return std::move(Err); + if (auto *RD = dyn_cast<CXXRecordDecl>(FromDecl)) + FromElemTy = Importer.FromContext.getRecordType(RD); + else + FromElemTy = cast<ValueDecl>(FromDecl)->getType(); + ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType( + ImpDecl, FromPath[LoopIdx].getAsBaseOrMember().getInt())); + } else { + FromElemTy = + Importer.FromContext.getAsArrayType(FromElemTy)->getElementType(); + ToPath[LoopIdx] = APValue::LValuePathEntry::ArrayIndex( + FromPath[LoopIdx].getAsArrayIndex()); + } + } + } else + Result.setLValue(Base, Offset, APValue::NoLValuePath{}, + FromValue.isNullPointer()); + } + if (Err) + return std::move(Err); + return Result; +} + Expected<DeclarationName> ASTImporter::HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS, diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 919d322..c6b2c47 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -360,7 +360,6 @@ llvm::APSInt ConstantExpr::getResultAsAPSInt() const { } APValue ConstantExpr::getAPValueResult() const { - assert(hasAPValueResult()); switch (ConstantExprBits.ResultKind) { case ConstantExpr::RSK_APValue: @@ -370,6 +369,8 @@ APValue ConstantExpr::getAPValueResult() const { llvm::APSInt(llvm::APInt(ConstantExprBits.BitWidth, Int64Result()), ConstantExprBits.IsUnsigned)); case ConstantExpr::RSK_None: + if (ConstantExprBits.APValueKind == APValue::Indeterminate) + return APValue::IndeterminateValue(); return APValue(); } llvm_unreachable("invalid ResultKind"); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index b2780db..79fabfe 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -8963,48 +8963,146 @@ ReadFixedPointSemantics(const SmallVectorImpl<uint64_t> &Record, HasUnsignedPadding); } -static const llvm::fltSemantics & -readAPFloatSemantics(ASTRecordReader &reader) { - return llvm::APFloatBase::EnumToSemantics( - static_cast<llvm::APFloatBase::Semantics>(reader.readInt())); -} - APValue ASTRecordReader::readAPValue() { - unsigned Kind = readInt(); - switch ((APValue::ValueKind) Kind) { + 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(readAPSInt()); + return APValue(asImpl().readAPSInt()); case APValue::Float: { - const llvm::fltSemantics &FloatSema = readAPFloatSemantics(*this); - return APValue(readAPFloat(FloatSema)); + 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 = readAPSInt(); - return APValue(std::move(First), readAPSInt()); + llvm::APSInt First = asImpl().readAPSInt(); + return APValue(std::move(First), asImpl().readAPSInt()); } case APValue::ComplexFloat: { - const llvm::fltSemantics &FloatSema1 = readAPFloatSemantics(*this); - llvm::APFloat First = readAPFloat(FloatSema1); - const llvm::fltSemantics &FloatSema2 = readAPFloatSemantics(*this); - return APValue(std::move(First), readAPFloat(FloatSema2)); - } - case APValue::LValue: - case APValue::Vector: - case APValue::Array: - case APValue::Struct: - case APValue::Union: - case APValue::MemberPointer: - case APValue::AddrLabelDiff: - // TODO : Handle all these APValue::ValueKind. - return APValue(); + 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(); + 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"); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ed00a3b..bbc8248 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5155,22 +5155,103 @@ void ASTRecordWriter::AddAPValue(const APValue &Value) { 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()); - push_back(static_cast<uint64_t>(llvm::APFloatBase::SemanticsToEnum( - Value.getComplexFloatImag().getSemantics()))); AddAPFloat(Value.getComplexFloatImag()); return; } - case APValue::LValue: 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)); + 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: - case APValue::MemberPointer: + AddDeclRef(Value.getUnionField()); + AddAPValue(Value.getUnionValue()); + return; case APValue::AddrLabelDiff: - // TODO : Handle all these APValue::ValueKind. + 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"); |