Path: blob/main/contrib/llvm-project/clang/lib/AST/APValue.cpp
35260 views
//===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the APValue class.9//10//===----------------------------------------------------------------------===//1112#include "clang/AST/APValue.h"13#include "Linkage.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/ExprCXX.h"19#include "clang/AST/Type.h"20#include "llvm/Support/ErrorHandling.h"21#include "llvm/Support/raw_ostream.h"22using namespace clang;2324/// The identity of a type_info object depends on the canonical unqualified25/// type only.26TypeInfoLValue::TypeInfoLValue(const Type *T)27: T(T->getCanonicalTypeUnqualified().getTypePtr()) {}2829void TypeInfoLValue::print(llvm::raw_ostream &Out,30const PrintingPolicy &Policy) const {31Out << "typeid(";32QualType(getType(), 0).print(Out, Policy);33Out << ")";34}3536static_assert(371 << llvm::PointerLikeTypeTraits<TypeInfoLValue>::NumLowBitsAvailable <=38alignof(Type),39"Type is insufficiently aligned");4041APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V)42: Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()) : nullptr), Local{I, V} {}43APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V)44: Ptr(P), Local{I, V} {}4546APValue::LValueBase APValue::LValueBase::getDynamicAlloc(DynamicAllocLValue LV,47QualType Type) {48LValueBase Base;49Base.Ptr = LV;50Base.DynamicAllocType = Type.getAsOpaquePtr();51return Base;52}5354APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV,55QualType TypeInfo) {56LValueBase Base;57Base.Ptr = LV;58Base.TypeInfoType = TypeInfo.getAsOpaquePtr();59return Base;60}6162QualType APValue::LValueBase::getType() const {63if (!*this) return QualType();64if (const ValueDecl *D = dyn_cast<const ValueDecl*>()) {65// FIXME: It's unclear where we're supposed to take the type from, and66// this actually matters for arrays of unknown bound. Eg:67//68// extern int arr[]; void f() { extern int arr[3]; };69// constexpr int *p = &arr[1]; // valid?70//71// For now, we take the most complete type we can find.72for (auto *Redecl = cast<ValueDecl>(D->getMostRecentDecl()); Redecl;73Redecl = cast_or_null<ValueDecl>(Redecl->getPreviousDecl())) {74QualType T = Redecl->getType();75if (!T->isIncompleteArrayType())76return T;77}78return D->getType();79}8081if (is<TypeInfoLValue>())82return getTypeInfoType();8384if (is<DynamicAllocLValue>())85return getDynamicAllocType();8687const Expr *Base = get<const Expr*>();8889// For a materialized temporary, the type of the temporary we materialized90// may not be the type of the expression.91if (const MaterializeTemporaryExpr *MTE =92llvm::dyn_cast<MaterializeTemporaryExpr>(Base)) {93SmallVector<const Expr *, 2> CommaLHSs;94SmallVector<SubobjectAdjustment, 2> Adjustments;95const Expr *Temp = MTE->getSubExpr();96const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs,97Adjustments);98// Keep any cv-qualifiers from the reference if we generated a temporary99// for it directly. Otherwise use the type after adjustment.100if (!Adjustments.empty())101return Inner->getType();102}103104return Base->getType();105}106107unsigned APValue::LValueBase::getCallIndex() const {108return (is<TypeInfoLValue>() || is<DynamicAllocLValue>()) ? 0109: Local.CallIndex;110}111112unsigned APValue::LValueBase::getVersion() const {113return (is<TypeInfoLValue>() || is<DynamicAllocLValue>()) ? 0 : Local.Version;114}115116QualType APValue::LValueBase::getTypeInfoType() const {117assert(is<TypeInfoLValue>() && "not a type_info lvalue");118return QualType::getFromOpaquePtr(TypeInfoType);119}120121QualType APValue::LValueBase::getDynamicAllocType() const {122assert(is<DynamicAllocLValue>() && "not a dynamic allocation lvalue");123return QualType::getFromOpaquePtr(DynamicAllocType);124}125126void APValue::LValueBase::Profile(llvm::FoldingSetNodeID &ID) const {127ID.AddPointer(Ptr.getOpaqueValue());128if (is<TypeInfoLValue>() || is<DynamicAllocLValue>())129return;130ID.AddInteger(Local.CallIndex);131ID.AddInteger(Local.Version);132}133134namespace clang {135bool operator==(const APValue::LValueBase &LHS,136const APValue::LValueBase &RHS) {137if (LHS.Ptr != RHS.Ptr)138return false;139if (LHS.is<TypeInfoLValue>() || LHS.is<DynamicAllocLValue>())140return true;141return LHS.Local.CallIndex == RHS.Local.CallIndex &&142LHS.Local.Version == RHS.Local.Version;143}144}145146APValue::LValuePathEntry::LValuePathEntry(BaseOrMemberType BaseOrMember) {147if (const Decl *D = BaseOrMember.getPointer())148BaseOrMember.setPointer(D->getCanonicalDecl());149Value = reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue());150}151152void APValue::LValuePathEntry::Profile(llvm::FoldingSetNodeID &ID) const {153ID.AddInteger(Value);154}155156APValue::LValuePathSerializationHelper::LValuePathSerializationHelper(157ArrayRef<LValuePathEntry> Path, QualType ElemTy)158: Ty((const void *)ElemTy.getTypePtrOrNull()), Path(Path) {}159160QualType APValue::LValuePathSerializationHelper::getType() {161return QualType::getFromOpaquePtr(Ty);162}163164namespace {165struct LVBase {166APValue::LValueBase Base;167CharUnits Offset;168unsigned PathLength;169bool IsNullPtr : 1;170bool IsOnePastTheEnd : 1;171};172}173174void *APValue::LValueBase::getOpaqueValue() const {175return Ptr.getOpaqueValue();176}177178bool APValue::LValueBase::isNull() const {179return Ptr.isNull();180}181182APValue::LValueBase::operator bool () const {183return static_cast<bool>(Ptr);184}185186clang::APValue::LValueBase187llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {188clang::APValue::LValueBase B;189B.Ptr = DenseMapInfo<const ValueDecl*>::getEmptyKey();190return B;191}192193clang::APValue::LValueBase194llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {195clang::APValue::LValueBase B;196B.Ptr = DenseMapInfo<const ValueDecl*>::getTombstoneKey();197return B;198}199200namespace clang {201llvm::hash_code hash_value(const APValue::LValueBase &Base) {202if (Base.is<TypeInfoLValue>() || Base.is<DynamicAllocLValue>())203return llvm::hash_value(Base.getOpaqueValue());204return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(),205Base.getVersion());206}207}208209unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue(210const clang::APValue::LValueBase &Base) {211return hash_value(Base);212}213214bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual(215const clang::APValue::LValueBase &LHS,216const clang::APValue::LValueBase &RHS) {217return LHS == RHS;218}219220struct APValue::LV : LVBase {221static const unsigned InlinePathSpace =222(DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry);223224/// Path - The sequence of base classes, fields and array indices to follow to225/// walk from Base to the subobject. When performing GCC-style folding, there226/// may not be such a path.227union {228LValuePathEntry Path[InlinePathSpace];229LValuePathEntry *PathPtr;230};231232LV() { PathLength = (unsigned)-1; }233~LV() { resizePath(0); }234235void resizePath(unsigned Length) {236if (Length == PathLength)237return;238if (hasPathPtr())239delete [] PathPtr;240PathLength = Length;241if (hasPathPtr())242PathPtr = new LValuePathEntry[Length];243}244245bool hasPath() const { return PathLength != (unsigned)-1; }246bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }247248LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }249const LValuePathEntry *getPath() const {250return hasPathPtr() ? PathPtr : Path;251}252};253254namespace {255struct MemberPointerBase {256llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember;257unsigned PathLength;258};259}260261struct APValue::MemberPointerData : MemberPointerBase {262static const unsigned InlinePathSpace =263(DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*);264typedef const CXXRecordDecl *PathElem;265union {266PathElem Path[InlinePathSpace];267PathElem *PathPtr;268};269270MemberPointerData() { PathLength = 0; }271~MemberPointerData() { resizePath(0); }272273void resizePath(unsigned Length) {274if (Length == PathLength)275return;276if (hasPathPtr())277delete [] PathPtr;278PathLength = Length;279if (hasPathPtr())280PathPtr = new PathElem[Length];281}282283bool hasPathPtr() const { return PathLength > InlinePathSpace; }284285PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; }286const PathElem *getPath() const {287return hasPathPtr() ? PathPtr : Path;288}289};290291// FIXME: Reduce the malloc traffic here.292293APValue::Arr::Arr(unsigned NumElts, unsigned Size) :294Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]),295NumElts(NumElts), ArrSize(Size) {}296APValue::Arr::~Arr() { delete [] Elts; }297298APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) :299Elts(new APValue[NumBases+NumFields]),300NumBases(NumBases), NumFields(NumFields) {}301APValue::StructData::~StructData() {302delete [] Elts;303}304305APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {}306APValue::UnionData::~UnionData () {307delete Value;308}309310APValue::APValue(const APValue &RHS) : Kind(None) {311switch (RHS.getKind()) {312case None:313case Indeterminate:314Kind = RHS.getKind();315break;316case Int:317MakeInt();318setInt(RHS.getInt());319break;320case Float:321MakeFloat();322setFloat(RHS.getFloat());323break;324case FixedPoint: {325APFixedPoint FXCopy = RHS.getFixedPoint();326MakeFixedPoint(std::move(FXCopy));327break;328}329case Vector:330MakeVector();331setVector(((const Vec *)(const char *)&RHS.Data)->Elts,332RHS.getVectorLength());333break;334case ComplexInt:335MakeComplexInt();336setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());337break;338case ComplexFloat:339MakeComplexFloat();340setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());341break;342case LValue:343MakeLValue();344if (RHS.hasLValuePath())345setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),346RHS.isLValueOnePastTheEnd(), RHS.isNullPointer());347else348setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),349RHS.isNullPointer());350break;351case Array:352MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());353for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)354getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);355if (RHS.hasArrayFiller())356getArrayFiller() = RHS.getArrayFiller();357break;358case Struct:359MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());360for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I)361getStructBase(I) = RHS.getStructBase(I);362for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I)363getStructField(I) = RHS.getStructField(I);364break;365case Union:366MakeUnion();367setUnion(RHS.getUnionField(), RHS.getUnionValue());368break;369case MemberPointer:370MakeMemberPointer(RHS.getMemberPointerDecl(),371RHS.isMemberPointerToDerivedMember(),372RHS.getMemberPointerPath());373break;374case AddrLabelDiff:375MakeAddrLabelDiff();376setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS());377break;378}379}380381APValue::APValue(APValue &&RHS) : Kind(RHS.Kind), Data(RHS.Data) {382RHS.Kind = None;383}384385APValue &APValue::operator=(const APValue &RHS) {386if (this != &RHS)387*this = APValue(RHS);388return *this;389}390391APValue &APValue::operator=(APValue &&RHS) {392if (this != &RHS) {393if (Kind != None && Kind != Indeterminate)394DestroyDataAndMakeUninit();395Kind = RHS.Kind;396Data = RHS.Data;397RHS.Kind = None;398}399return *this;400}401402void APValue::DestroyDataAndMakeUninit() {403if (Kind == Int)404((APSInt *)(char *)&Data)->~APSInt();405else if (Kind == Float)406((APFloat *)(char *)&Data)->~APFloat();407else if (Kind == FixedPoint)408((APFixedPoint *)(char *)&Data)->~APFixedPoint();409else if (Kind == Vector)410((Vec *)(char *)&Data)->~Vec();411else if (Kind == ComplexInt)412((ComplexAPSInt *)(char *)&Data)->~ComplexAPSInt();413else if (Kind == ComplexFloat)414((ComplexAPFloat *)(char *)&Data)->~ComplexAPFloat();415else if (Kind == LValue)416((LV *)(char *)&Data)->~LV();417else if (Kind == Array)418((Arr *)(char *)&Data)->~Arr();419else if (Kind == Struct)420((StructData *)(char *)&Data)->~StructData();421else if (Kind == Union)422((UnionData *)(char *)&Data)->~UnionData();423else if (Kind == MemberPointer)424((MemberPointerData *)(char *)&Data)->~MemberPointerData();425else if (Kind == AddrLabelDiff)426((AddrLabelDiffData *)(char *)&Data)->~AddrLabelDiffData();427Kind = None;428}429430bool APValue::needsCleanup() const {431switch (getKind()) {432case None:433case Indeterminate:434case AddrLabelDiff:435return false;436case Struct:437case Union:438case Array:439case Vector:440return true;441case Int:442return getInt().needsCleanup();443case Float:444return getFloat().needsCleanup();445case FixedPoint:446return getFixedPoint().getValue().needsCleanup();447case ComplexFloat:448assert(getComplexFloatImag().needsCleanup() ==449getComplexFloatReal().needsCleanup() &&450"In _Complex float types, real and imaginary values always have the "451"same size.");452return getComplexFloatReal().needsCleanup();453case ComplexInt:454assert(getComplexIntImag().needsCleanup() ==455getComplexIntReal().needsCleanup() &&456"In _Complex int types, real and imaginary values must have the "457"same size.");458return getComplexIntReal().needsCleanup();459case LValue:460return reinterpret_cast<const LV *>(&Data)->hasPathPtr();461case MemberPointer:462return reinterpret_cast<const MemberPointerData *>(&Data)->hasPathPtr();463}464llvm_unreachable("Unknown APValue kind!");465}466467void APValue::swap(APValue &RHS) {468std::swap(Kind, RHS.Kind);469std::swap(Data, RHS.Data);470}471472/// Profile the value of an APInt, excluding its bit-width.473static void profileIntValue(llvm::FoldingSetNodeID &ID, const llvm::APInt &V) {474for (unsigned I = 0, N = V.getBitWidth(); I < N; I += 32)475ID.AddInteger((uint32_t)V.extractBitsAsZExtValue(std::min(32u, N - I), I));476}477478void APValue::Profile(llvm::FoldingSetNodeID &ID) const {479// Note that our profiling assumes that only APValues of the same type are480// ever compared. As a result, we don't consider collisions that could only481// happen if the types are different. (For example, structs with different482// numbers of members could profile the same.)483484ID.AddInteger(Kind);485486switch (Kind) {487case None:488case Indeterminate:489return;490491case AddrLabelDiff:492ID.AddPointer(getAddrLabelDiffLHS()->getLabel()->getCanonicalDecl());493ID.AddPointer(getAddrLabelDiffRHS()->getLabel()->getCanonicalDecl());494return;495496case Struct:497for (unsigned I = 0, N = getStructNumBases(); I != N; ++I)498getStructBase(I).Profile(ID);499for (unsigned I = 0, N = getStructNumFields(); I != N; ++I)500getStructField(I).Profile(ID);501return;502503case Union:504if (!getUnionField()) {505ID.AddInteger(0);506return;507}508ID.AddInteger(getUnionField()->getFieldIndex() + 1);509getUnionValue().Profile(ID);510return;511512case Array: {513if (getArraySize() == 0)514return;515516// The profile should not depend on whether the array is expanded or517// not, but we don't want to profile the array filler many times for518// a large array. So treat all equal trailing elements as the filler.519// Elements are profiled in reverse order to support this, and the520// first profiled element is followed by a count. For example:521//522// ['a', 'c', 'x', 'x', 'x'] is profiled as523// [5, 'x', 3, 'c', 'a']524llvm::FoldingSetNodeID FillerID;525(hasArrayFiller() ? getArrayFiller()526: getArrayInitializedElt(getArrayInitializedElts() - 1))527.Profile(FillerID);528ID.AddNodeID(FillerID);529unsigned NumFillers = getArraySize() - getArrayInitializedElts();530unsigned N = getArrayInitializedElts();531532// Count the number of elements equal to the last one. This loop ends533// by adding an integer indicating the number of such elements, with534// N set to the number of elements left to profile.535while (true) {536if (N == 0) {537// All elements are fillers.538assert(NumFillers == getArraySize());539ID.AddInteger(NumFillers);540break;541}542543// No need to check if the last element is equal to the last544// element.545if (N != getArraySize()) {546llvm::FoldingSetNodeID ElemID;547getArrayInitializedElt(N - 1).Profile(ElemID);548if (ElemID != FillerID) {549ID.AddInteger(NumFillers);550ID.AddNodeID(ElemID);551--N;552break;553}554}555556// This is a filler.557++NumFillers;558--N;559}560561// Emit the remaining elements.562for (; N != 0; --N)563getArrayInitializedElt(N - 1).Profile(ID);564return;565}566567case Vector:568for (unsigned I = 0, N = getVectorLength(); I != N; ++I)569getVectorElt(I).Profile(ID);570return;571572case Int:573profileIntValue(ID, getInt());574return;575576case Float:577profileIntValue(ID, getFloat().bitcastToAPInt());578return;579580case FixedPoint:581profileIntValue(ID, getFixedPoint().getValue());582return;583584case ComplexFloat:585profileIntValue(ID, getComplexFloatReal().bitcastToAPInt());586profileIntValue(ID, getComplexFloatImag().bitcastToAPInt());587return;588589case ComplexInt:590profileIntValue(ID, getComplexIntReal());591profileIntValue(ID, getComplexIntImag());592return;593594case LValue:595getLValueBase().Profile(ID);596ID.AddInteger(getLValueOffset().getQuantity());597ID.AddInteger((isNullPointer() ? 1 : 0) |598(isLValueOnePastTheEnd() ? 2 : 0) |599(hasLValuePath() ? 4 : 0));600if (hasLValuePath()) {601ID.AddInteger(getLValuePath().size());602// For uniqueness, we only need to profile the entries corresponding603// to union members, but we don't have the type here so we don't know604// how to interpret the entries.605for (LValuePathEntry E : getLValuePath())606E.Profile(ID);607}608return;609610case MemberPointer:611ID.AddPointer(getMemberPointerDecl());612ID.AddInteger(isMemberPointerToDerivedMember());613for (const CXXRecordDecl *D : getMemberPointerPath())614ID.AddPointer(D);615return;616}617618llvm_unreachable("Unknown APValue kind!");619}620621static double GetApproxValue(const llvm::APFloat &F) {622llvm::APFloat V = F;623bool ignored;624V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,625&ignored);626return V.convertToDouble();627}628629static bool TryPrintAsStringLiteral(raw_ostream &Out,630const PrintingPolicy &Policy,631const ArrayType *ATy,632ArrayRef<APValue> Inits) {633if (Inits.empty())634return false;635636QualType Ty = ATy->getElementType();637if (!Ty->isAnyCharacterType())638return false;639640// Nothing we can do about a sequence that is not null-terminated641if (!Inits.back().isInt() || !Inits.back().getInt().isZero())642return false;643644Inits = Inits.drop_back();645646llvm::SmallString<40> Buf;647Buf.push_back('"');648649// Better than printing a two-digit sequence of 10 integers.650constexpr size_t MaxN = 36;651StringRef Ellipsis;652if (Inits.size() > MaxN && !Policy.EntireContentsOfLargeArray) {653Ellipsis = "[...]";654Inits =655Inits.take_front(std::min(MaxN - Ellipsis.size() / 2, Inits.size()));656}657658for (auto &Val : Inits) {659if (!Val.isInt())660return false;661int64_t Char64 = Val.getInt().getExtValue();662if (!isASCII(Char64))663return false; // Bye bye, see you in integers.664auto Ch = static_cast<unsigned char>(Char64);665// The diagnostic message is 'quoted'666StringRef Escaped = escapeCStyle<EscapeChar::SingleAndDouble>(Ch);667if (Escaped.empty()) {668if (!isPrintable(Ch))669return false;670Buf.emplace_back(Ch);671} else {672Buf.append(Escaped);673}674}675676Buf.append(Ellipsis);677Buf.push_back('"');678679if (Ty->isWideCharType())680Out << 'L';681else if (Ty->isChar8Type())682Out << "u8";683else if (Ty->isChar16Type())684Out << 'u';685else if (Ty->isChar32Type())686Out << 'U';687688Out << Buf;689return true;690}691692void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx,693QualType Ty) const {694printPretty(Out, Ctx.getPrintingPolicy(), Ty, &Ctx);695}696697void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy,698QualType Ty, const ASTContext *Ctx) const {699// There are no objects of type 'void', but values of this type can be700// returned from functions.701if (Ty->isVoidType()) {702Out << "void()";703return;704}705706if (const auto *AT = Ty->getAs<AtomicType>())707Ty = AT->getValueType();708709switch (getKind()) {710case APValue::None:711Out << "<out of lifetime>";712return;713case APValue::Indeterminate:714Out << "<uninitialized>";715return;716case APValue::Int:717if (Ty->isBooleanType())718Out << (getInt().getBoolValue() ? "true" : "false");719else720Out << getInt();721return;722case APValue::Float:723Out << GetApproxValue(getFloat());724return;725case APValue::FixedPoint:726Out << getFixedPoint();727return;728case APValue::Vector: {729Out << '{';730QualType ElemTy = Ty->castAs<VectorType>()->getElementType();731getVectorElt(0).printPretty(Out, Policy, ElemTy, Ctx);732for (unsigned i = 1; i != getVectorLength(); ++i) {733Out << ", ";734getVectorElt(i).printPretty(Out, Policy, ElemTy, Ctx);735}736Out << '}';737return;738}739case APValue::ComplexInt:740Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";741return;742case APValue::ComplexFloat:743Out << GetApproxValue(getComplexFloatReal()) << "+"744<< GetApproxValue(getComplexFloatImag()) << "i";745return;746case APValue::LValue: {747bool IsReference = Ty->isReferenceType();748QualType InnerTy749= IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();750if (InnerTy.isNull())751InnerTy = Ty;752753LValueBase Base = getLValueBase();754if (!Base) {755if (isNullPointer()) {756Out << (Policy.Nullptr ? "nullptr" : "0");757} else if (IsReference) {758Out << "*(" << InnerTy.stream(Policy) << "*)"759<< getLValueOffset().getQuantity();760} else {761Out << "(" << Ty.stream(Policy) << ")"762<< getLValueOffset().getQuantity();763}764return;765}766767if (!hasLValuePath()) {768// No lvalue path: just print the offset.769CharUnits O = getLValueOffset();770CharUnits S = Ctx ? Ctx->getTypeSizeInCharsIfKnown(InnerTy).value_or(771CharUnits::Zero())772: CharUnits::Zero();773if (!O.isZero()) {774if (IsReference)775Out << "*(";776if (S.isZero() || O % S) {777Out << "(char*)";778S = CharUnits::One();779}780Out << '&';781} else if (!IsReference) {782Out << '&';783}784785if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())786Out << *VD;787else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) {788TI.print(Out, Policy);789} else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) {790Out << "{*new "791<< Base.getDynamicAllocType().stream(Policy) << "#"792<< DA.getIndex() << "}";793} else {794assert(Base.get<const Expr *>() != nullptr &&795"Expecting non-null Expr");796Base.get<const Expr*>()->printPretty(Out, nullptr, Policy);797}798799if (!O.isZero()) {800Out << " + " << (O / S);801if (IsReference)802Out << ')';803}804return;805}806807// We have an lvalue path. Print it out nicely.808if (!IsReference)809Out << '&';810else if (isLValueOnePastTheEnd())811Out << "*(&";812813QualType ElemTy = Base.getType();814if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {815Out << *VD;816} else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) {817TI.print(Out, Policy);818} else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) {819Out << "{*new " << Base.getDynamicAllocType().stream(Policy) << "#"820<< DA.getIndex() << "}";821} else {822const Expr *E = Base.get<const Expr*>();823assert(E != nullptr && "Expecting non-null Expr");824E->printPretty(Out, nullptr, Policy);825}826827ArrayRef<LValuePathEntry> Path = getLValuePath();828const CXXRecordDecl *CastToBase = nullptr;829for (unsigned I = 0, N = Path.size(); I != N; ++I) {830if (ElemTy->isRecordType()) {831// The lvalue refers to a class type, so the next path entry is a base832// or member.833const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer();834if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {835CastToBase = RD;836// Leave ElemTy referring to the most-derived class. The actual type837// doesn't matter except for array types.838} else {839const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);840Out << ".";841if (CastToBase)842Out << *CastToBase << "::";843Out << *VD;844ElemTy = VD->getType();845}846} else if (ElemTy->isAnyComplexType()) {847// The lvalue refers to a complex type848Out << (Path[I].getAsArrayIndex() == 0 ? ".real" : ".imag");849ElemTy = ElemTy->castAs<ComplexType>()->getElementType();850} else {851// The lvalue must refer to an array.852Out << '[' << Path[I].getAsArrayIndex() << ']';853ElemTy = ElemTy->castAsArrayTypeUnsafe()->getElementType();854}855}856857// Handle formatting of one-past-the-end lvalues.858if (isLValueOnePastTheEnd()) {859// FIXME: If CastToBase is non-0, we should prefix the output with860// "(CastToBase*)".861Out << " + 1";862if (IsReference)863Out << ')';864}865return;866}867case APValue::Array: {868const ArrayType *AT = Ty->castAsArrayTypeUnsafe();869unsigned N = getArrayInitializedElts();870if (N != 0 && TryPrintAsStringLiteral(Out, Policy, AT,871{&getArrayInitializedElt(0), N}))872return;873QualType ElemTy = AT->getElementType();874Out << '{';875unsigned I = 0;876switch (N) {877case 0:878for (; I != N; ++I) {879Out << ", ";880if (I == 10 && !Policy.EntireContentsOfLargeArray) {881Out << "...}";882return;883}884[[fallthrough]];885default:886getArrayInitializedElt(I).printPretty(Out, Policy, ElemTy, Ctx);887}888}889Out << '}';890return;891}892case APValue::Struct: {893Out << '{';894const RecordDecl *RD = Ty->castAs<RecordType>()->getDecl();895bool First = true;896if (unsigned N = getStructNumBases()) {897const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);898CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();899for (unsigned I = 0; I != N; ++I, ++BI) {900assert(BI != CD->bases_end());901if (!First)902Out << ", ";903getStructBase(I).printPretty(Out, Policy, BI->getType(), Ctx);904First = false;905}906}907for (const auto *FI : RD->fields()) {908if (!First)909Out << ", ";910if (FI->isUnnamedBitField())911continue;912getStructField(FI->getFieldIndex()).913printPretty(Out, Policy, FI->getType(), Ctx);914First = false;915}916Out << '}';917return;918}919case APValue::Union:920Out << '{';921if (const FieldDecl *FD = getUnionField()) {922Out << "." << *FD << " = ";923getUnionValue().printPretty(Out, Policy, FD->getType(), Ctx);924}925Out << '}';926return;927case APValue::MemberPointer:928// FIXME: This is not enough to unambiguously identify the member in a929// multiple-inheritance scenario.930if (const ValueDecl *VD = getMemberPointerDecl()) {931Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;932return;933}934Out << "0";935return;936case APValue::AddrLabelDiff:937Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName();938Out << " - ";939Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName();940return;941}942llvm_unreachable("Unknown APValue kind!");943}944945std::string APValue::getAsString(const ASTContext &Ctx, QualType Ty) const {946std::string Result;947llvm::raw_string_ostream Out(Result);948printPretty(Out, Ctx, Ty);949Out.flush();950return Result;951}952953bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy,954const ASTContext &Ctx) const {955if (isInt()) {956Result = getInt();957return true;958}959960if (isLValue() && isNullPointer()) {961Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy);962return true;963}964965if (isLValue() && !getLValueBase()) {966Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy);967return true;968}969970return false;971}972973const APValue::LValueBase APValue::getLValueBase() const {974assert(isLValue() && "Invalid accessor");975return ((const LV *)(const void *)&Data)->Base;976}977978bool APValue::isLValueOnePastTheEnd() const {979assert(isLValue() && "Invalid accessor");980return ((const LV *)(const void *)&Data)->IsOnePastTheEnd;981}982983CharUnits &APValue::getLValueOffset() {984assert(isLValue() && "Invalid accessor");985return ((LV *)(void *)&Data)->Offset;986}987988bool APValue::hasLValuePath() const {989assert(isLValue() && "Invalid accessor");990return ((const LV *)(const char *)&Data)->hasPath();991}992993ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {994assert(isLValue() && hasLValuePath() && "Invalid accessor");995const LV &LVal = *((const LV *)(const char *)&Data);996return llvm::ArrayRef(LVal.getPath(), LVal.PathLength);997}998999unsigned APValue::getLValueCallIndex() const {1000assert(isLValue() && "Invalid accessor");1001return ((const LV *)(const char *)&Data)->Base.getCallIndex();1002}10031004unsigned APValue::getLValueVersion() const {1005assert(isLValue() && "Invalid accessor");1006return ((const LV *)(const char *)&Data)->Base.getVersion();1007}10081009bool APValue::isNullPointer() const {1010assert(isLValue() && "Invalid usage");1011return ((const LV *)(const char *)&Data)->IsNullPtr;1012}10131014void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,1015bool IsNullPtr) {1016assert(isLValue() && "Invalid accessor");1017LV &LVal = *((LV *)(char *)&Data);1018LVal.Base = B;1019LVal.IsOnePastTheEnd = false;1020LVal.Offset = O;1021LVal.resizePath((unsigned)-1);1022LVal.IsNullPtr = IsNullPtr;1023}10241025MutableArrayRef<APValue::LValuePathEntry>1026APValue::setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size,1027bool IsOnePastTheEnd, bool IsNullPtr) {1028assert(isLValue() && "Invalid accessor");1029LV &LVal = *((LV *)(char *)&Data);1030LVal.Base = B;1031LVal.IsOnePastTheEnd = IsOnePastTheEnd;1032LVal.Offset = O;1033LVal.IsNullPtr = IsNullPtr;1034LVal.resizePath(Size);1035return {LVal.getPath(), Size};1036}10371038void APValue::setLValue(LValueBase B, const CharUnits &O,1039ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,1040bool IsNullPtr) {1041MutableArrayRef<APValue::LValuePathEntry> InternalPath =1042setLValueUninit(B, O, Path.size(), IsOnePastTheEnd, IsNullPtr);1043if (Path.size()) {1044memcpy(InternalPath.data(), Path.data(),1045Path.size() * sizeof(LValuePathEntry));1046}1047}10481049void APValue::setUnion(const FieldDecl *Field, const APValue &Value) {1050assert(isUnion() && "Invalid accessor");1051((UnionData *)(char *)&Data)->Field =1052Field ? Field->getCanonicalDecl() : nullptr;1053*((UnionData *)(char *)&Data)->Value = Value;1054}10551056const ValueDecl *APValue::getMemberPointerDecl() const {1057assert(isMemberPointer() && "Invalid accessor");1058const MemberPointerData &MPD =1059*((const MemberPointerData *)(const char *)&Data);1060return MPD.MemberAndIsDerivedMember.getPointer();1061}10621063bool APValue::isMemberPointerToDerivedMember() const {1064assert(isMemberPointer() && "Invalid accessor");1065const MemberPointerData &MPD =1066*((const MemberPointerData *)(const char *)&Data);1067return MPD.MemberAndIsDerivedMember.getInt();1068}10691070ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {1071assert(isMemberPointer() && "Invalid accessor");1072const MemberPointerData &MPD =1073*((const MemberPointerData *)(const char *)&Data);1074return llvm::ArrayRef(MPD.getPath(), MPD.PathLength);1075}10761077void APValue::MakeLValue() {1078assert(isAbsent() && "Bad state change");1079static_assert(sizeof(LV) <= DataSize, "LV too big");1080new ((void *)(char *)&Data) LV();1081Kind = LValue;1082}10831084void APValue::MakeArray(unsigned InitElts, unsigned Size) {1085assert(isAbsent() && "Bad state change");1086new ((void *)(char *)&Data) Arr(InitElts, Size);1087Kind = Array;1088}10891090MutableArrayRef<APValue::LValuePathEntry>1091setLValueUninit(APValue::LValueBase B, const CharUnits &O, unsigned Size,1092bool OnePastTheEnd, bool IsNullPtr);10931094MutableArrayRef<const CXXRecordDecl *>1095APValue::setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember,1096unsigned Size) {1097assert(isAbsent() && "Bad state change");1098MemberPointerData *MPD = new ((void *)(char *)&Data) MemberPointerData;1099Kind = MemberPointer;1100MPD->MemberAndIsDerivedMember.setPointer(1101Member ? cast<ValueDecl>(Member->getCanonicalDecl()) : nullptr);1102MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);1103MPD->resizePath(Size);1104return {MPD->getPath(), MPD->PathLength};1105}11061107void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,1108ArrayRef<const CXXRecordDecl *> Path) {1109MutableArrayRef<const CXXRecordDecl *> InternalPath =1110setMemberPointerUninit(Member, IsDerivedMember, Path.size());1111for (unsigned I = 0; I != Path.size(); ++I)1112InternalPath[I] = Path[I]->getCanonicalDecl();1113}11141115LinkageInfo LinkageComputer::getLVForValue(const APValue &V,1116LVComputationKind computation) {1117LinkageInfo LV = LinkageInfo::external();11181119auto MergeLV = [&](LinkageInfo MergeLV) {1120LV.merge(MergeLV);1121return LV.getLinkage() == Linkage::Internal;1122};1123auto Merge = [&](const APValue &V) {1124return MergeLV(getLVForValue(V, computation));1125};11261127switch (V.getKind()) {1128case APValue::None:1129case APValue::Indeterminate:1130case APValue::Int:1131case APValue::Float:1132case APValue::FixedPoint:1133case APValue::ComplexInt:1134case APValue::ComplexFloat:1135case APValue::Vector:1136break;11371138case APValue::AddrLabelDiff:1139// Even for an inline function, it's not reasonable to treat a difference1140// between the addresses of labels as an external value.1141return LinkageInfo::internal();11421143case APValue::Struct: {1144for (unsigned I = 0, N = V.getStructNumBases(); I != N; ++I)1145if (Merge(V.getStructBase(I)))1146break;1147for (unsigned I = 0, N = V.getStructNumFields(); I != N; ++I)1148if (Merge(V.getStructField(I)))1149break;1150break;1151}11521153case APValue::Union:1154if (V.getUnionField())1155Merge(V.getUnionValue());1156break;11571158case APValue::Array: {1159for (unsigned I = 0, N = V.getArrayInitializedElts(); I != N; ++I)1160if (Merge(V.getArrayInitializedElt(I)))1161break;1162if (V.hasArrayFiller())1163Merge(V.getArrayFiller());1164break;1165}11661167case APValue::LValue: {1168if (!V.getLValueBase()) {1169// Null or absolute address: this is external.1170} else if (const auto *VD =1171V.getLValueBase().dyn_cast<const ValueDecl *>()) {1172if (VD && MergeLV(getLVForDecl(VD, computation)))1173break;1174} else if (const auto TI = V.getLValueBase().dyn_cast<TypeInfoLValue>()) {1175if (MergeLV(getLVForType(*TI.getType(), computation)))1176break;1177} else if (const Expr *E = V.getLValueBase().dyn_cast<const Expr *>()) {1178// Almost all expression bases are internal. The exception is1179// lifetime-extended temporaries.1180// FIXME: These should be modeled as having the1181// LifetimeExtendedTemporaryDecl itself as the base.1182// FIXME: If we permit Objective-C object literals in template arguments,1183// they should not imply internal linkage.1184auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E);1185if (!MTE || MTE->getStorageDuration() == SD_FullExpression)1186return LinkageInfo::internal();1187if (MergeLV(getLVForDecl(MTE->getExtendingDecl(), computation)))1188break;1189} else {1190assert(V.getLValueBase().is<DynamicAllocLValue>() &&1191"unexpected LValueBase kind");1192return LinkageInfo::internal();1193}1194// The lvalue path doesn't matter: pointers to all subobjects always have1195// the same visibility as pointers to the complete object.1196break;1197}11981199case APValue::MemberPointer:1200if (const NamedDecl *D = V.getMemberPointerDecl())1201MergeLV(getLVForDecl(D, computation));1202// Note that we could have a base-to-derived conversion here to a member of1203// a derived class with less linkage/visibility. That's covered by the1204// linkage and visibility of the value's type.1205break;1206}12071208return LV;1209}121012111212