diff options
author | 2020-08-03 14:31:31 +0000 | |
---|---|---|
committer | 2020-08-03 14:31:31 +0000 | |
commit | e5dd70708596ae51455a0ffa086a00c5b29f8583 (patch) | |
tree | 5d676f27b570bacf71e786c3b5cff3e6f6679b59 /gnu/llvm/clang/lib/AST/APValue.cpp | |
parent | Import LLVM 10.0.0 release including clang, lld and lldb. (diff) | |
download | wireguard-openbsd-e5dd70708596ae51455a0ffa086a00c5b29f8583.tar.xz wireguard-openbsd-e5dd70708596ae51455a0ffa086a00c5b29f8583.zip |
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom
tested by plenty
Diffstat (limited to 'gnu/llvm/clang/lib/AST/APValue.cpp')
-rw-r--r-- | gnu/llvm/clang/lib/AST/APValue.cpp | 841 |
1 files changed, 841 insertions, 0 deletions
diff --git a/gnu/llvm/clang/lib/AST/APValue.cpp b/gnu/llvm/clang/lib/AST/APValue.cpp new file mode 100644 index 00000000000..50f8d05dacb --- /dev/null +++ b/gnu/llvm/clang/lib/AST/APValue.cpp @@ -0,0 +1,841 @@ +//===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the APValue class. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/APValue.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Type.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; + +/// The identity of a type_info object depends on the canonical unqualified +/// type only. +TypeInfoLValue::TypeInfoLValue(const Type *T) + : T(T->getCanonicalTypeUnqualified().getTypePtr()) {} + +void TypeInfoLValue::print(llvm::raw_ostream &Out, + const PrintingPolicy &Policy) const { + Out << "typeid("; + QualType(getType(), 0).print(Out, Policy); + Out << ")"; +} + +static_assert( + 1 << llvm::PointerLikeTypeTraits<TypeInfoLValue>::NumLowBitsAvailable <= + alignof(Type), + "Type is insufficiently aligned"); + +APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V) + : Ptr(P), Local{I, V} {} +APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V) + : Ptr(P), Local{I, V} {} + +APValue::LValueBase APValue::LValueBase::getDynamicAlloc(DynamicAllocLValue LV, + QualType Type) { + LValueBase Base; + Base.Ptr = LV; + Base.DynamicAllocType = Type.getAsOpaquePtr(); + return Base; +} + +APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV, + QualType TypeInfo) { + LValueBase Base; + Base.Ptr = LV; + Base.TypeInfoType = TypeInfo.getAsOpaquePtr(); + return Base; +} + +unsigned APValue::LValueBase::getCallIndex() const { + return (is<TypeInfoLValue>() || is<DynamicAllocLValue>()) ? 0 + : Local.CallIndex; +} + +unsigned APValue::LValueBase::getVersion() const { + return (is<TypeInfoLValue>() || is<DynamicAllocLValue>()) ? 0 : Local.Version; +} + +QualType APValue::LValueBase::getTypeInfoType() const { + assert(is<TypeInfoLValue>() && "not a type_info lvalue"); + return QualType::getFromOpaquePtr(TypeInfoType); +} + +QualType APValue::LValueBase::getDynamicAllocType() const { + assert(is<DynamicAllocLValue>() && "not a dynamic allocation lvalue"); + return QualType::getFromOpaquePtr(DynamicAllocType); +} + +namespace clang { +bool operator==(const APValue::LValueBase &LHS, + const APValue::LValueBase &RHS) { + if (LHS.Ptr != RHS.Ptr) + return false; + if (LHS.is<TypeInfoLValue>()) + return true; + return LHS.Local.CallIndex == RHS.Local.CallIndex && + LHS.Local.Version == RHS.Local.Version; +} +} + +namespace { + struct LVBase { + APValue::LValueBase Base; + CharUnits Offset; + unsigned PathLength; + bool IsNullPtr : 1; + bool IsOnePastTheEnd : 1; + }; +} + +void *APValue::LValueBase::getOpaqueValue() const { + return Ptr.getOpaqueValue(); +} + +bool APValue::LValueBase::isNull() const { + return Ptr.isNull(); +} + +APValue::LValueBase::operator bool () const { + return static_cast<bool>(Ptr); +} + +clang::APValue::LValueBase +llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() { + return clang::APValue::LValueBase( + DenseMapInfo<const ValueDecl*>::getEmptyKey()); +} + +clang::APValue::LValueBase +llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() { + return clang::APValue::LValueBase( + DenseMapInfo<const ValueDecl*>::getTombstoneKey()); +} + +namespace clang { +llvm::hash_code hash_value(const APValue::LValueBase &Base) { + if (Base.is<TypeInfoLValue>() || Base.is<DynamicAllocLValue>()) + return llvm::hash_value(Base.getOpaqueValue()); + return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(), + Base.getVersion()); +} +} + +unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue( + const clang::APValue::LValueBase &Base) { + return hash_value(Base); +} + +bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual( + const clang::APValue::LValueBase &LHS, + const clang::APValue::LValueBase &RHS) { + return LHS == RHS; +} + +struct APValue::LV : LVBase { + static const unsigned InlinePathSpace = + (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry); + + /// Path - The sequence of base classes, fields and array indices to follow to + /// walk from Base to the subobject. When performing GCC-style folding, there + /// may not be such a path. + union { + LValuePathEntry Path[InlinePathSpace]; + LValuePathEntry *PathPtr; + }; + + LV() { PathLength = (unsigned)-1; } + ~LV() { resizePath(0); } + + void resizePath(unsigned Length) { + if (Length == PathLength) + return; + if (hasPathPtr()) + delete [] PathPtr; + PathLength = Length; + if (hasPathPtr()) + PathPtr = new LValuePathEntry[Length]; + } + + bool hasPath() const { return PathLength != (unsigned)-1; } + bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; } + + LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; } + const LValuePathEntry *getPath() const { + return hasPathPtr() ? PathPtr : Path; + } +}; + +namespace { + struct MemberPointerBase { + llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember; + unsigned PathLength; + }; +} + +struct APValue::MemberPointerData : MemberPointerBase { + static const unsigned InlinePathSpace = + (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); + typedef const CXXRecordDecl *PathElem; + union { + PathElem Path[InlinePathSpace]; + PathElem *PathPtr; + }; + + MemberPointerData() { PathLength = 0; } + ~MemberPointerData() { resizePath(0); } + + void resizePath(unsigned Length) { + if (Length == PathLength) + return; + if (hasPathPtr()) + delete [] PathPtr; + PathLength = Length; + if (hasPathPtr()) + PathPtr = new PathElem[Length]; + } + + bool hasPathPtr() const { return PathLength > InlinePathSpace; } + + PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; } + const PathElem *getPath() const { + return hasPathPtr() ? PathPtr : Path; + } +}; + +// FIXME: Reduce the malloc traffic here. + +APValue::Arr::Arr(unsigned NumElts, unsigned Size) : + Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]), + NumElts(NumElts), ArrSize(Size) {} +APValue::Arr::~Arr() { delete [] Elts; } + +APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) : + Elts(new APValue[NumBases+NumFields]), + NumBases(NumBases), NumFields(NumFields) {} +APValue::StructData::~StructData() { + delete [] Elts; +} + +APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {} +APValue::UnionData::~UnionData () { + delete Value; +} + +APValue::APValue(const APValue &RHS) : Kind(None) { + switch (RHS.getKind()) { + case None: + case Indeterminate: + Kind = RHS.getKind(); + break; + case Int: + MakeInt(); + setInt(RHS.getInt()); + break; + case Float: + MakeFloat(); + setFloat(RHS.getFloat()); + break; + case FixedPoint: { + APFixedPoint FXCopy = RHS.getFixedPoint(); + MakeFixedPoint(std::move(FXCopy)); + break; + } + case Vector: + MakeVector(); + setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, + RHS.getVectorLength()); + break; + case ComplexInt: + MakeComplexInt(); + setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag()); + break; + case ComplexFloat: + MakeComplexFloat(); + setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag()); + break; + case LValue: + MakeLValue(); + if (RHS.hasLValuePath()) + setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), + RHS.isLValueOnePastTheEnd(), RHS.isNullPointer()); + else + setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), + RHS.isNullPointer()); + break; + case Array: + MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); + for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I) + getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I); + if (RHS.hasArrayFiller()) + getArrayFiller() = RHS.getArrayFiller(); + break; + case Struct: + MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields()); + for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I) + getStructBase(I) = RHS.getStructBase(I); + for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I) + getStructField(I) = RHS.getStructField(I); + break; + case Union: + MakeUnion(); + setUnion(RHS.getUnionField(), RHS.getUnionValue()); + break; + case MemberPointer: + MakeMemberPointer(RHS.getMemberPointerDecl(), + RHS.isMemberPointerToDerivedMember(), + RHS.getMemberPointerPath()); + break; + case AddrLabelDiff: + MakeAddrLabelDiff(); + setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS()); + break; + } +} + +void APValue::DestroyDataAndMakeUninit() { + if (Kind == Int) + ((APSInt*)(char*)Data.buffer)->~APSInt(); + else if (Kind == Float) + ((APFloat*)(char*)Data.buffer)->~APFloat(); + else if (Kind == FixedPoint) + ((APFixedPoint *)(char *)Data.buffer)->~APFixedPoint(); + else if (Kind == Vector) + ((Vec*)(char*)Data.buffer)->~Vec(); + else if (Kind == ComplexInt) + ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt(); + else if (Kind == ComplexFloat) + ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat(); + else if (Kind == LValue) + ((LV*)(char*)Data.buffer)->~LV(); + else if (Kind == Array) + ((Arr*)(char*)Data.buffer)->~Arr(); + else if (Kind == Struct) + ((StructData*)(char*)Data.buffer)->~StructData(); + else if (Kind == Union) + ((UnionData*)(char*)Data.buffer)->~UnionData(); + else if (Kind == MemberPointer) + ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData(); + else if (Kind == AddrLabelDiff) + ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData(); + Kind = None; +} + +bool APValue::needsCleanup() const { + switch (getKind()) { + case None: + case Indeterminate: + case AddrLabelDiff: + return false; + case Struct: + case Union: + case Array: + case Vector: + return true; + case Int: + return getInt().needsCleanup(); + case Float: + return getFloat().needsCleanup(); + case FixedPoint: + return getFixedPoint().getValue().needsCleanup(); + case ComplexFloat: + assert(getComplexFloatImag().needsCleanup() == + getComplexFloatReal().needsCleanup() && + "In _Complex float types, real and imaginary values always have the " + "same size."); + return getComplexFloatReal().needsCleanup(); + case ComplexInt: + assert(getComplexIntImag().needsCleanup() == + getComplexIntReal().needsCleanup() && + "In _Complex int types, real and imaginary values must have the " + "same size."); + return getComplexIntReal().needsCleanup(); + case LValue: + return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr(); + case MemberPointer: + return reinterpret_cast<const MemberPointerData *>(Data.buffer) + ->hasPathPtr(); + } + llvm_unreachable("Unknown APValue kind!"); +} + +void APValue::swap(APValue &RHS) { + std::swap(Kind, RHS.Kind); + char TmpData[DataSize]; + memcpy(TmpData, Data.buffer, DataSize); + memcpy(Data.buffer, RHS.Data.buffer, DataSize); + memcpy(RHS.Data.buffer, TmpData, DataSize); +} + +LLVM_DUMP_METHOD void APValue::dump() const { + dump(llvm::errs()); + llvm::errs() << '\n'; +} + +static double GetApproxValue(const llvm::APFloat &F) { + llvm::APFloat V = F; + bool ignored; + V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven, + &ignored); + return V.convertToDouble(); +} + +void APValue::dump(raw_ostream &OS) const { + switch (getKind()) { + case None: + OS << "None"; + return; + case Indeterminate: + OS << "Indeterminate"; + return; + case Int: + OS << "Int: " << getInt(); + return; + case Float: + OS << "Float: " << GetApproxValue(getFloat()); + return; + case FixedPoint: + OS << "FixedPoint : " << getFixedPoint(); + return; + case Vector: + OS << "Vector: "; + getVectorElt(0).dump(OS); + for (unsigned i = 1; i != getVectorLength(); ++i) { + OS << ", "; + getVectorElt(i).dump(OS); + } + return; + case ComplexInt: + OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag(); + return; + case ComplexFloat: + OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal()) + << ", " << GetApproxValue(getComplexFloatImag()); + return; + case LValue: + OS << "LValue: <todo>"; + return; + case Array: + OS << "Array: "; + for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) { + getArrayInitializedElt(I).dump(OS); + if (I != getArraySize() - 1) OS << ", "; + } + if (hasArrayFiller()) { + OS << getArraySize() - getArrayInitializedElts() << " x "; + getArrayFiller().dump(OS); + } + return; + case Struct: + OS << "Struct "; + if (unsigned N = getStructNumBases()) { + OS << " bases: "; + getStructBase(0).dump(OS); + for (unsigned I = 1; I != N; ++I) { + OS << ", "; + getStructBase(I).dump(OS); + } + } + if (unsigned N = getStructNumFields()) { + OS << " fields: "; + getStructField(0).dump(OS); + for (unsigned I = 1; I != N; ++I) { + OS << ", "; + getStructField(I).dump(OS); + } + } + return; + case Union: + OS << "Union: "; + getUnionValue().dump(OS); + return; + case MemberPointer: + OS << "MemberPointer: <todo>"; + return; + case AddrLabelDiff: + OS << "AddrLabelDiff: <todo>"; + return; + } + llvm_unreachable("Unknown APValue kind!"); +} + +void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, + QualType Ty) const { + switch (getKind()) { + case APValue::None: + Out << "<out of lifetime>"; + return; + case APValue::Indeterminate: + Out << "<uninitialized>"; + return; + case APValue::Int: + if (Ty->isBooleanType()) + Out << (getInt().getBoolValue() ? "true" : "false"); + else + Out << getInt(); + return; + case APValue::Float: + Out << GetApproxValue(getFloat()); + return; + case APValue::FixedPoint: + Out << getFixedPoint(); + return; + case APValue::Vector: { + Out << '{'; + QualType ElemTy = Ty->castAs<VectorType>()->getElementType(); + getVectorElt(0).printPretty(Out, Ctx, ElemTy); + for (unsigned i = 1; i != getVectorLength(); ++i) { + Out << ", "; + getVectorElt(i).printPretty(Out, Ctx, ElemTy); + } + Out << '}'; + return; + } + case APValue::ComplexInt: + Out << getComplexIntReal() << "+" << getComplexIntImag() << "i"; + return; + case APValue::ComplexFloat: + Out << GetApproxValue(getComplexFloatReal()) << "+" + << GetApproxValue(getComplexFloatImag()) << "i"; + return; + case APValue::LValue: { + bool IsReference = Ty->isReferenceType(); + QualType InnerTy + = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType(); + if (InnerTy.isNull()) + InnerTy = Ty; + + LValueBase Base = getLValueBase(); + if (!Base) { + if (isNullPointer()) { + Out << (Ctx.getLangOpts().CPlusPlus11 ? "nullptr" : "0"); + } else if (IsReference) { + Out << "*(" << InnerTy.stream(Ctx.getPrintingPolicy()) << "*)" + << getLValueOffset().getQuantity(); + } else { + Out << "(" << Ty.stream(Ctx.getPrintingPolicy()) << ")" + << getLValueOffset().getQuantity(); + } + return; + } + + if (!hasLValuePath()) { + // No lvalue path: just print the offset. + CharUnits O = getLValueOffset(); + CharUnits S = Ctx.getTypeSizeInChars(InnerTy); + if (!O.isZero()) { + if (IsReference) + Out << "*("; + if (O % S) { + Out << "(char*)"; + S = CharUnits::One(); + } + Out << '&'; + } else if (!IsReference) { + Out << '&'; + } + + if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) + Out << *VD; + else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) { + TI.print(Out, Ctx.getPrintingPolicy()); + } else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) { + Out << "{*new " + << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" + << DA.getIndex() << "}"; + } else { + assert(Base.get<const Expr *>() != nullptr && + "Expecting non-null Expr"); + Base.get<const Expr*>()->printPretty(Out, nullptr, + Ctx.getPrintingPolicy()); + } + + if (!O.isZero()) { + Out << " + " << (O / S); + if (IsReference) + Out << ')'; + } + return; + } + + // We have an lvalue path. Print it out nicely. + if (!IsReference) + Out << '&'; + else if (isLValueOnePastTheEnd()) + Out << "*(&"; + + QualType ElemTy; + if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) { + Out << *VD; + ElemTy = VD->getType(); + } else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) { + TI.print(Out, Ctx.getPrintingPolicy()); + ElemTy = Base.getTypeInfoType(); + } else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) { + Out << "{*new " + << Base.getDynamicAllocType().stream(Ctx.getPrintingPolicy()) << "#" + << DA.getIndex() << "}"; + ElemTy = Base.getDynamicAllocType(); + } else { + const Expr *E = Base.get<const Expr*>(); + assert(E != nullptr && "Expecting non-null Expr"); + E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); + // FIXME: This is wrong if E is a MaterializeTemporaryExpr with an lvalue + // adjustment. + ElemTy = E->getType(); + } + + ArrayRef<LValuePathEntry> Path = getLValuePath(); + const CXXRecordDecl *CastToBase = nullptr; + for (unsigned I = 0, N = Path.size(); I != N; ++I) { + if (ElemTy->getAs<RecordType>()) { + // The lvalue refers to a class type, so the next path entry is a base + // or member. + const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer(); + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) { + CastToBase = RD; + ElemTy = Ctx.getRecordType(RD); + } else { + const ValueDecl *VD = cast<ValueDecl>(BaseOrMember); + Out << "."; + if (CastToBase) + Out << *CastToBase << "::"; + Out << *VD; + ElemTy = VD->getType(); + } + } else { + // The lvalue must refer to an array. + Out << '[' << Path[I].getAsArrayIndex() << ']'; + ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType(); + } + } + + // Handle formatting of one-past-the-end lvalues. + if (isLValueOnePastTheEnd()) { + // FIXME: If CastToBase is non-0, we should prefix the output with + // "(CastToBase*)". + Out << " + 1"; + if (IsReference) + Out << ')'; + } + return; + } + case APValue::Array: { + const ArrayType *AT = Ctx.getAsArrayType(Ty); + QualType ElemTy = AT->getElementType(); + Out << '{'; + if (unsigned N = getArrayInitializedElts()) { + getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy); + for (unsigned I = 1; I != N; ++I) { + Out << ", "; + if (I == 10) { + // Avoid printing out the entire contents of large arrays. + Out << "..."; + break; + } + getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy); + } + } + Out << '}'; + return; + } + case APValue::Struct: { + Out << '{'; + const RecordDecl *RD = Ty->castAs<RecordType>()->getDecl(); + bool First = true; + if (unsigned N = getStructNumBases()) { + const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD); + CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin(); + for (unsigned I = 0; I != N; ++I, ++BI) { + assert(BI != CD->bases_end()); + if (!First) + Out << ", "; + getStructBase(I).printPretty(Out, Ctx, BI->getType()); + First = false; + } + } + for (const auto *FI : RD->fields()) { + if (!First) + Out << ", "; + if (FI->isUnnamedBitfield()) continue; + getStructField(FI->getFieldIndex()). + printPretty(Out, Ctx, FI->getType()); + First = false; + } + Out << '}'; + return; + } + case APValue::Union: + Out << '{'; + if (const FieldDecl *FD = getUnionField()) { + Out << "." << *FD << " = "; + getUnionValue().printPretty(Out, Ctx, FD->getType()); + } + Out << '}'; + return; + case APValue::MemberPointer: + // FIXME: This is not enough to unambiguously identify the member in a + // multiple-inheritance scenario. + if (const ValueDecl *VD = getMemberPointerDecl()) { + Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD; + return; + } + Out << "0"; + return; + case APValue::AddrLabelDiff: + Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName(); + Out << " - "; + Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName(); + return; + } + llvm_unreachable("Unknown APValue kind!"); +} + +std::string APValue::getAsString(const ASTContext &Ctx, QualType Ty) const { + std::string Result; + llvm::raw_string_ostream Out(Result); + printPretty(Out, Ctx, Ty); + Out.flush(); + return Result; +} + +bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy, + const ASTContext &Ctx) const { + if (isInt()) { + Result = getInt(); + return true; + } + + if (isLValue() && isNullPointer()) { + Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy); + return true; + } + + if (isLValue() && !getLValueBase()) { + Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy); + return true; + } + + return false; +} + +const APValue::LValueBase APValue::getLValueBase() const { + assert(isLValue() && "Invalid accessor"); + return ((const LV*)(const void*)Data.buffer)->Base; +} + +bool APValue::isLValueOnePastTheEnd() const { + assert(isLValue() && "Invalid accessor"); + return ((const LV*)(const void*)Data.buffer)->IsOnePastTheEnd; +} + +CharUnits &APValue::getLValueOffset() { + assert(isLValue() && "Invalid accessor"); + return ((LV*)(void*)Data.buffer)->Offset; +} + +bool APValue::hasLValuePath() const { + assert(isLValue() && "Invalid accessor"); + return ((const LV*)(const char*)Data.buffer)->hasPath(); +} + +ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { + assert(isLValue() && hasLValuePath() && "Invalid accessor"); + const LV &LVal = *((const LV*)(const char*)Data.buffer); + return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength); +} + +unsigned APValue::getLValueCallIndex() const { + assert(isLValue() && "Invalid accessor"); + return ((const LV*)(const char*)Data.buffer)->Base.getCallIndex(); +} + +unsigned APValue::getLValueVersion() const { + assert(isLValue() && "Invalid accessor"); + return ((const LV*)(const char*)Data.buffer)->Base.getVersion(); +} + +bool APValue::isNullPointer() const { + assert(isLValue() && "Invalid usage"); + return ((const LV*)(const char*)Data.buffer)->IsNullPtr; +} + +void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, + bool IsNullPtr) { + assert(isLValue() && "Invalid accessor"); + LV &LVal = *((LV*)(char*)Data.buffer); + LVal.Base = B; + LVal.IsOnePastTheEnd = false; + LVal.Offset = O; + LVal.resizePath((unsigned)-1); + LVal.IsNullPtr = IsNullPtr; +} + +void APValue::setLValue(LValueBase B, const CharUnits &O, + ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, + bool IsNullPtr) { + assert(isLValue() && "Invalid accessor"); + 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; +} + +const ValueDecl *APValue::getMemberPointerDecl() const { + assert(isMemberPointer() && "Invalid accessor"); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); + return MPD.MemberAndIsDerivedMember.getPointer(); +} + +bool APValue::isMemberPointerToDerivedMember() const { + assert(isMemberPointer() && "Invalid accessor"); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); + return MPD.MemberAndIsDerivedMember.getInt(); +} + +ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { + assert(isMemberPointer() && "Invalid accessor"); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); + return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength); +} + +void APValue::MakeLValue() { + assert(isAbsent() && "Bad state change"); + static_assert(sizeof(LV) <= DataSize, "LV too big"); + new ((void*)(char*)Data.buffer) LV(); + Kind = LValue; +} + +void APValue::MakeArray(unsigned InitElts, unsigned Size) { + assert(isAbsent() && "Bad state change"); + new ((void*)(char*)Data.buffer) Arr(InitElts, Size); + Kind = Array; +} + +void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef<const CXXRecordDecl*> Path) { + assert(isAbsent() && "Bad state change"); + MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; + Kind = MemberPointer; + MPD->MemberAndIsDerivedMember.setPointer(Member); + MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); + MPD->resizePath(Path.size()); + memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*)); +} |