aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorTyker <tyker1@outlook.com>2020-10-01 17:58:07 +0200
committerTyker <tyker1@outlook.com>2020-10-21 19:03:13 +0200
commitcf34dd0c4e84b69bb901f9cd4f3491852238ec44 (patch)
tree374f9f672a18ddc70ca83abf8c0354fe2c4afda7 /clang/lib
parent8b7dac81d378c339d3e55f6f51cd0c42803903ad (diff)
downloadllvm-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.cpp43
-rw-r--r--clang/lib/AST/ASTContext.cpp3
-rw-r--r--clang/lib/AST/ASTImporter.cpp183
-rw-r--r--clang/lib/AST/Expr.cpp3
-rw-r--r--clang/lib/Serialization/ASTReader.cpp152
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp91
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");