1 //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements the APValue class.
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/APValue.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/CharUnits.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/Expr.h"
18 #include "clang/AST/Type.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/raw_ostream.h"
21 using namespace clang;
23 /// The identity of a type_info object depends on the canonical unqualified
25 TypeInfoLValue::TypeInfoLValue(const Type *T)
26 : T(T->getCanonicalTypeUnqualified().getTypePtr()) {}
28 void TypeInfoLValue::print(llvm::raw_ostream &Out,
29 const PrintingPolicy &Policy) const {
31 QualType(getType(), 0).print(Out, Policy);
36 1 << llvm::PointerLikeTypeTraits<TypeInfoLValue>::NumLowBitsAvailable <=
38 "Type is insufficiently aligned");
40 APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V)
41 : Ptr(P), Local{I, V} {}
42 APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V)
43 : Ptr(P), Local{I, V} {}
45 APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV,
49 Base.TypeInfoType = TypeInfo.getAsOpaquePtr();
53 unsigned APValue::LValueBase::getCallIndex() const {
54 return is<TypeInfoLValue>() ? 0 : Local.CallIndex;
57 unsigned APValue::LValueBase::getVersion() const {
58 return is<TypeInfoLValue>() ? 0 : Local.Version;
61 QualType APValue::LValueBase::getTypeInfoType() const {
62 assert(is<TypeInfoLValue>() && "not a type_info lvalue");
63 return QualType::getFromOpaquePtr(TypeInfoType);
67 bool operator==(const APValue::LValueBase &LHS,
68 const APValue::LValueBase &RHS) {
69 if (LHS.Ptr != RHS.Ptr)
71 if (LHS.is<TypeInfoLValue>())
73 return LHS.Local.CallIndex == RHS.Local.CallIndex &&
74 LHS.Local.Version == RHS.Local.Version;
80 APValue::LValueBase Base;
84 bool IsOnePastTheEnd : 1;
88 void *APValue::LValueBase::getOpaqueValue() const {
89 return Ptr.getOpaqueValue();
92 bool APValue::LValueBase::isNull() const {
96 APValue::LValueBase::operator bool () const {
97 return static_cast<bool>(Ptr);
100 clang::APValue::LValueBase
101 llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
102 return clang::APValue::LValueBase(
103 DenseMapInfo<const ValueDecl*>::getEmptyKey());
106 clang::APValue::LValueBase
107 llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
108 return clang::APValue::LValueBase(
109 DenseMapInfo<const ValueDecl*>::getTombstoneKey());
113 llvm::hash_code hash_value(const APValue::LValueBase &Base) {
114 if (Base.is<TypeInfoLValue>())
115 return llvm::hash_value(Base.getOpaqueValue());
116 return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(),
121 unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue(
122 const clang::APValue::LValueBase &Base) {
123 return hash_value(Base);
126 bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual(
127 const clang::APValue::LValueBase &LHS,
128 const clang::APValue::LValueBase &RHS) {
132 struct APValue::LV : LVBase {
133 static const unsigned InlinePathSpace =
134 (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
136 /// Path - The sequence of base classes, fields and array indices to follow to
137 /// walk from Base to the subobject. When performing GCC-style folding, there
138 /// may not be such a path.
140 LValuePathEntry Path[InlinePathSpace];
141 LValuePathEntry *PathPtr;
144 LV() { PathLength = (unsigned)-1; }
145 ~LV() { resizePath(0); }
147 void resizePath(unsigned Length) {
148 if (Length == PathLength)
154 PathPtr = new LValuePathEntry[Length];
157 bool hasPath() const { return PathLength != (unsigned)-1; }
158 bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }
160 LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }
161 const LValuePathEntry *getPath() const {
162 return hasPathPtr() ? PathPtr : Path;
167 struct MemberPointerBase {
168 llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember;
173 struct APValue::MemberPointerData : MemberPointerBase {
174 static const unsigned InlinePathSpace =
175 (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*);
176 typedef const CXXRecordDecl *PathElem;
178 PathElem Path[InlinePathSpace];
182 MemberPointerData() { PathLength = 0; }
183 ~MemberPointerData() { resizePath(0); }
185 void resizePath(unsigned Length) {
186 if (Length == PathLength)
192 PathPtr = new PathElem[Length];
195 bool hasPathPtr() const { return PathLength > InlinePathSpace; }
197 PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; }
198 const PathElem *getPath() const {
199 return hasPathPtr() ? PathPtr : Path;
203 // FIXME: Reduce the malloc traffic here.
205 APValue::Arr::Arr(unsigned NumElts, unsigned Size) :
206 Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]),
207 NumElts(NumElts), ArrSize(Size) {}
208 APValue::Arr::~Arr() { delete [] Elts; }
210 APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) :
211 Elts(new APValue[NumBases+NumFields]),
212 NumBases(NumBases), NumFields(NumFields) {}
213 APValue::StructData::~StructData() {
217 APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {}
218 APValue::UnionData::~UnionData () {
222 APValue::APValue(const APValue &RHS) : Kind(None) {
223 switch (RHS.getKind()) {
226 Kind = RHS.getKind();
230 setInt(RHS.getInt());
234 setFloat(RHS.getFloat());
237 APFixedPoint FXCopy = RHS.getFixedPoint();
238 MakeFixedPoint(std::move(FXCopy));
243 setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts,
244 RHS.getVectorLength());
248 setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
252 setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
256 if (RHS.hasLValuePath())
257 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
258 RHS.isLValueOnePastTheEnd(), RHS.isNullPointer());
260 setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
261 RHS.isNullPointer());
264 MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
265 for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)
266 getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);
267 if (RHS.hasArrayFiller())
268 getArrayFiller() = RHS.getArrayFiller();
271 MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());
272 for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I)
273 getStructBase(I) = RHS.getStructBase(I);
274 for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I)
275 getStructField(I) = RHS.getStructField(I);
279 setUnion(RHS.getUnionField(), RHS.getUnionValue());
282 MakeMemberPointer(RHS.getMemberPointerDecl(),
283 RHS.isMemberPointerToDerivedMember(),
284 RHS.getMemberPointerPath());
288 setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS());
293 void APValue::DestroyDataAndMakeUninit() {
295 ((APSInt*)(char*)Data.buffer)->~APSInt();
296 else if (Kind == Float)
297 ((APFloat*)(char*)Data.buffer)->~APFloat();
298 else if (Kind == FixedPoint)
299 ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint();
300 else if (Kind == Vector)
301 ((Vec*)(char*)Data.buffer)->~Vec();
302 else if (Kind == ComplexInt)
303 ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt();
304 else if (Kind == ComplexFloat)
305 ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat();
306 else if (Kind == LValue)
307 ((LV*)(char*)Data.buffer)->~LV();
308 else if (Kind == Array)
309 ((Arr*)(char*)Data.buffer)->~Arr();
310 else if (Kind == Struct)
311 ((StructData*)(char*)Data.buffer)->~StructData();
312 else if (Kind == Union)
313 ((UnionData*)(char*)Data.buffer)->~UnionData();
314 else if (Kind == MemberPointer)
315 ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData();
316 else if (Kind == AddrLabelDiff)
317 ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData();
321 bool APValue::needsCleanup() const {
333 return getInt().needsCleanup();
335 return getFloat().needsCleanup();
337 return getFixedPoint().getValue().needsCleanup();
339 assert(getComplexFloatImag().needsCleanup() ==
340 getComplexFloatReal().needsCleanup() &&
341 "In _Complex float types, real and imaginary values always have the "
343 return getComplexFloatReal().needsCleanup();
345 assert(getComplexIntImag().needsCleanup() ==
346 getComplexIntReal().needsCleanup() &&
347 "In _Complex int types, real and imaginary values must have the "
349 return getComplexIntReal().needsCleanup();
351 return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr();
353 return reinterpret_cast<const MemberPointerData *>(Data.buffer)
356 llvm_unreachable("Unknown APValue kind!");
359 void APValue::swap(APValue &RHS) {
360 std::swap(Kind, RHS.Kind);
361 char TmpData[DataSize];
362 memcpy(TmpData, Data.buffer, DataSize);
363 memcpy(Data.buffer, RHS.Data.buffer, DataSize);
364 memcpy(RHS.Data.buffer, TmpData, DataSize);
367 LLVM_DUMP_METHOD void APValue::dump() const {
369 llvm::errs() << '\n';
372 static double GetApproxValue(const llvm::APFloat &F) {
375 V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
377 return V.convertToDouble();
380 void APValue::dump(raw_ostream &OS) const {
386 OS << "Indeterminate";
389 OS << "Int: " << getInt();
392 OS << "Float: " << GetApproxValue(getFloat());
395 OS << "FixedPoint : " << getFixedPoint();
399 getVectorElt(0).dump(OS);
400 for (unsigned i = 1; i != getVectorLength(); ++i) {
402 getVectorElt(i).dump(OS);
406 OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
409 OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
410 << ", " << GetApproxValue(getComplexFloatImag());
413 OS << "LValue: <todo>";
417 for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
418 getArrayInitializedElt(I).dump(OS);
419 if (I != getArraySize() - 1) OS << ", ";
421 if (hasArrayFiller()) {
422 OS << getArraySize() - getArrayInitializedElts() << " x ";
423 getArrayFiller().dump(OS);
428 if (unsigned N = getStructNumBases()) {
430 getStructBase(0).dump(OS);
431 for (unsigned I = 1; I != N; ++I) {
433 getStructBase(I).dump(OS);
436 if (unsigned N = getStructNumFields()) {
438 getStructField(0).dump(OS);
439 for (unsigned I = 1; I != N; ++I) {
441 getStructField(I).dump(OS);
447 getUnionValue().dump(OS);
450 OS << "MemberPointer: <todo>";
453 OS << "AddrLabelDiff: <todo>";
456 llvm_unreachable("Unknown APValue kind!");
459 void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx,
463 Out << "<out of lifetime>";
465 case APValue::Indeterminate:
466 Out << "<uninitialized>";
469 if (Ty->isBooleanType())
470 Out << (getInt().getBoolValue() ? "true" : "false");
475 Out << GetApproxValue(getFloat());
477 case APValue::FixedPoint:
478 Out << getFixedPoint();
480 case APValue::Vector: {
482 QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
483 getVectorElt(0).printPretty(Out, Ctx, ElemTy);
484 for (unsigned i = 1; i != getVectorLength(); ++i) {
486 getVectorElt(i).printPretty(Out, Ctx, ElemTy);
491 case APValue::ComplexInt:
492 Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";
494 case APValue::ComplexFloat:
495 Out << GetApproxValue(getComplexFloatReal()) << "+"
496 << GetApproxValue(getComplexFloatImag()) << "i";
498 case APValue::LValue: {
499 bool IsReference = Ty->isReferenceType();
501 = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();
502 if (InnerTy.isNull())
505 LValueBase Base = getLValueBase();
507 if (isNullPointer()) {
508 Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0");
509 } else if (IsReference) {
510 Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)"
511 << getLValueOffset().getQuantity();
513 Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")"
514 << getLValueOffset().getQuantity();
519 if (!hasLValuePath()) {
520 // No lvalue path: just print the offset.
521 CharUnits O = getLValueOffset();
522 CharUnits S = Ctx.getTypeSizeInChars(InnerTy);
528 S = CharUnits::One();
531 } else if (!IsReference)
534 if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
536 else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) {
537 TI.print(Out, Ctx.getPrintingPolicy());
539 assert(Base.get<const Expr *>() != nullptr &&
540 "Expecting non-null Expr");
541 Base.get<const Expr*>()->printPretty(Out, nullptr,
542 Ctx.getPrintingPolicy());
546 Out << " + " << (O / S);
553 // We have an lvalue path. Print it out nicely.
556 else if (isLValueOnePastTheEnd())
560 if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
562 ElemTy = VD->getType();
563 } else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) {
564 TI.print(Out, Ctx.getPrintingPolicy());
565 ElemTy = Base.getTypeInfoType();
567 const Expr *E = Base.get<const Expr*>();
568 assert(E != nullptr && "Expecting non-null Expr");
569 E->printPretty(Out, nullptr, Ctx.getPrintingPolicy());
570 ElemTy = E->getType();
573 ArrayRef<LValuePathEntry> Path = getLValuePath();
574 const CXXRecordDecl *CastToBase = nullptr;
575 for (unsigned I = 0, N = Path.size(); I != N; ++I) {
576 if (ElemTy->getAs<RecordType>()) {
577 // The lvalue refers to a class type, so the next path entry is a base
579 const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer();
580 if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
582 ElemTy = Ctx.getRecordType(RD);
584 const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
587 Out << *CastToBase << "::";
589 ElemTy = VD->getType();
592 // The lvalue must refer to an array.
593 Out << '[' << Path[I].getAsArrayIndex() << ']';
594 ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType();
598 // Handle formatting of one-past-the-end lvalues.
599 if (isLValueOnePastTheEnd()) {
600 // FIXME: If CastToBase is non-0, we should prefix the output with
608 case APValue::Array: {
609 const ArrayType *AT = Ctx.getAsArrayType(Ty);
610 QualType ElemTy = AT->getElementType();
612 if (unsigned N = getArrayInitializedElts()) {
613 getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy);
614 for (unsigned I = 1; I != N; ++I) {
617 // Avoid printing out the entire contents of large arrays.
621 getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy);
627 case APValue::Struct: {
629 const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
631 if (unsigned N = getStructNumBases()) {
632 const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
633 CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
634 for (unsigned I = 0; I != N; ++I, ++BI) {
635 assert(BI != CD->bases_end());
638 getStructBase(I).printPretty(Out, Ctx, BI->getType());
642 for (const auto *FI : RD->fields()) {
645 if (FI->isUnnamedBitfield()) continue;
646 getStructField(FI->getFieldIndex()).
647 printPretty(Out, Ctx, FI->getType());
655 if (const FieldDecl *FD = getUnionField()) {
656 Out << "." << *FD << " = ";
657 getUnionValue().printPretty(Out, Ctx, FD->getType());
661 case APValue::MemberPointer:
662 // FIXME: This is not enough to unambiguously identify the member in a
663 // multiple-inheritance scenario.
664 if (const ValueDecl *VD = getMemberPointerDecl()) {
665 Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;
670 case APValue::AddrLabelDiff:
671 Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName();
673 Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName();
676 llvm_unreachable("Unknown APValue kind!");
679 std::string APValue::getAsString(const ASTContext &Ctx, QualType Ty) const {
681 llvm::raw_string_ostream Out(Result);
682 printPretty(Out, Ctx, Ty);
687 bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy,
688 const ASTContext &Ctx) const {
694 if (isLValue() && isNullPointer()) {
695 Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy);
699 if (isLValue() && !getLValueBase()) {
700 Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy);
707 const APValue::LValueBase APValue::getLValueBase() const {
708 assert(isLValue() && "Invalid accessor");
709 return ((const LV*)(const void*)Data.buffer)->Base;
712 bool APValue::isLValueOnePastTheEnd() const {
713 assert(isLValue() && "Invalid accessor");
714 return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd;
717 CharUnits &APValue::getLValueOffset() {
718 assert(isLValue() && "Invalid accessor");
719 return ((LV*)(void*)Data.buffer)->Offset;
722 bool APValue::hasLValuePath() const {
723 assert(isLValue() && "Invalid accessor");
724 return ((const LV*)(const char*)Data.buffer)->hasPath();
727 ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
728 assert(isLValue() && hasLValuePath() && "Invalid accessor");
729 const LV &LVal = *((const LV*)(const char*)Data.buffer);
730 return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength);
733 unsigned APValue::getLValueCallIndex() const {
734 assert(isLValue() && "Invalid accessor");
735 return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex();
738 unsigned APValue::getLValueVersion() const {
739 assert(isLValue() && "Invalid accessor");
740 return ((const LV*)(const char*)Data.buffer)->Base.getVersion();
743 bool APValue::isNullPointer() const {
744 assert(isLValue() && "Invalid usage");
745 return ((const LV*)(const char*)Data.buffer)->IsNullPtr;
748 void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
750 assert(isLValue() && "Invalid accessor");
751 LV &LVal = *((LV*)(char*)Data.buffer);
753 LVal.IsOnePastTheEnd = false;
755 LVal.resizePath((unsigned)-1);
756 LVal.IsNullPtr = IsNullPtr;
759 void APValue::setLValue(LValueBase B, const CharUnits &O,
760 ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
762 assert(isLValue() && "Invalid accessor");
763 LV &LVal = *((LV*)(char*)Data.buffer);
765 LVal.IsOnePastTheEnd = IsOnePastTheEnd;
767 LVal.resizePath(Path.size());
768 memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
769 LVal.IsNullPtr = IsNullPtr;
772 const ValueDecl *APValue::getMemberPointerDecl() const {
773 assert(isMemberPointer() && "Invalid accessor");
774 const MemberPointerData &MPD =
775 *((const MemberPointerData *)(const char *)Data.buffer);
776 return MPD.MemberAndIsDerivedMember.getPointer();
779 bool APValue::isMemberPointerToDerivedMember() const {
780 assert(isMemberPointer() && "Invalid accessor");
781 const MemberPointerData &MPD =
782 *((const MemberPointerData *)(const char *)Data.buffer);
783 return MPD.MemberAndIsDerivedMember.getInt();
786 ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {
787 assert(isMemberPointer() && "Invalid accessor");
788 const MemberPointerData &MPD =
789 *((const MemberPointerData *)(const char *)Data.buffer);
790 return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength);
793 void APValue::MakeLValue() {
794 assert(isAbsent() && "Bad state change");
795 static_assert(sizeof(LV) <= DataSize, "LV too big");
796 new ((void*)(char*)Data.buffer) LV();
800 void APValue::MakeArray(unsigned InitElts, unsigned Size) {
801 assert(isAbsent() && "Bad state change");
802 new ((void*)(char*)Data.buffer) Arr(InitElts, Size);
806 void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
807 ArrayRef<const CXXRecordDecl*> Path) {
808 assert(isAbsent() && "Bad state change");
809 MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData;
810 Kind = MemberPointer;
811 MPD->MemberAndIsDerivedMember.setPointer(Member);
812 MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
813 MPD->resizePath(Path.size());
814 memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));