1e5dd7070Spatrick //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements the APValue class.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick
13e5dd7070Spatrick #include "clang/AST/APValue.h"
14a9ac8606Spatrick #include "Linkage.h"
15e5dd7070Spatrick #include "clang/AST/ASTContext.h"
16e5dd7070Spatrick #include "clang/AST/CharUnits.h"
17e5dd7070Spatrick #include "clang/AST/DeclCXX.h"
18e5dd7070Spatrick #include "clang/AST/Expr.h"
19a9ac8606Spatrick #include "clang/AST/ExprCXX.h"
20e5dd7070Spatrick #include "clang/AST/Type.h"
21e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
22e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
23e5dd7070Spatrick using namespace clang;
24e5dd7070Spatrick
25e5dd7070Spatrick /// The identity of a type_info object depends on the canonical unqualified
26e5dd7070Spatrick /// type only.
TypeInfoLValue(const Type * T)27e5dd7070Spatrick TypeInfoLValue::TypeInfoLValue(const Type *T)
28e5dd7070Spatrick : T(T->getCanonicalTypeUnqualified().getTypePtr()) {}
29e5dd7070Spatrick
print(llvm::raw_ostream & Out,const PrintingPolicy & Policy) const30e5dd7070Spatrick void TypeInfoLValue::print(llvm::raw_ostream &Out,
31e5dd7070Spatrick const PrintingPolicy &Policy) const {
32e5dd7070Spatrick Out << "typeid(";
33e5dd7070Spatrick QualType(getType(), 0).print(Out, Policy);
34e5dd7070Spatrick Out << ")";
35e5dd7070Spatrick }
36e5dd7070Spatrick
37e5dd7070Spatrick static_assert(
38e5dd7070Spatrick 1 << llvm::PointerLikeTypeTraits<TypeInfoLValue>::NumLowBitsAvailable <=
39e5dd7070Spatrick alignof(Type),
40e5dd7070Spatrick "Type is insufficiently aligned");
41e5dd7070Spatrick
LValueBase(const ValueDecl * P,unsigned I,unsigned V)42e5dd7070Spatrick APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V)
43a9ac8606Spatrick : Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()) : nullptr), Local{I, V} {}
LValueBase(const Expr * P,unsigned I,unsigned V)44e5dd7070Spatrick APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V)
45e5dd7070Spatrick : Ptr(P), Local{I, V} {}
46e5dd7070Spatrick
getDynamicAlloc(DynamicAllocLValue LV,QualType Type)47e5dd7070Spatrick APValue::LValueBase APValue::LValueBase::getDynamicAlloc(DynamicAllocLValue LV,
48e5dd7070Spatrick QualType Type) {
49e5dd7070Spatrick LValueBase Base;
50e5dd7070Spatrick Base.Ptr = LV;
51e5dd7070Spatrick Base.DynamicAllocType = Type.getAsOpaquePtr();
52e5dd7070Spatrick return Base;
53e5dd7070Spatrick }
54e5dd7070Spatrick
getTypeInfo(TypeInfoLValue LV,QualType TypeInfo)55e5dd7070Spatrick APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV,
56e5dd7070Spatrick QualType TypeInfo) {
57e5dd7070Spatrick LValueBase Base;
58e5dd7070Spatrick Base.Ptr = LV;
59e5dd7070Spatrick Base.TypeInfoType = TypeInfo.getAsOpaquePtr();
60e5dd7070Spatrick return Base;
61e5dd7070Spatrick }
62e5dd7070Spatrick
getType() const63a9ac8606Spatrick QualType APValue::LValueBase::getType() const {
64a9ac8606Spatrick if (!*this) return QualType();
65a9ac8606Spatrick if (const ValueDecl *D = dyn_cast<const ValueDecl*>()) {
66a9ac8606Spatrick // FIXME: It's unclear where we're supposed to take the type from, and
67a9ac8606Spatrick // this actually matters for arrays of unknown bound. Eg:
68a9ac8606Spatrick //
69a9ac8606Spatrick // extern int arr[]; void f() { extern int arr[3]; };
70a9ac8606Spatrick // constexpr int *p = &arr[1]; // valid?
71a9ac8606Spatrick //
72a9ac8606Spatrick // For now, we take the most complete type we can find.
73a9ac8606Spatrick for (auto *Redecl = cast<ValueDecl>(D->getMostRecentDecl()); Redecl;
74a9ac8606Spatrick Redecl = cast_or_null<ValueDecl>(Redecl->getPreviousDecl())) {
75a9ac8606Spatrick QualType T = Redecl->getType();
76a9ac8606Spatrick if (!T->isIncompleteArrayType())
77a9ac8606Spatrick return T;
78a9ac8606Spatrick }
79a9ac8606Spatrick return D->getType();
80a9ac8606Spatrick }
81a9ac8606Spatrick
82a9ac8606Spatrick if (is<TypeInfoLValue>())
83a9ac8606Spatrick return getTypeInfoType();
84a9ac8606Spatrick
85a9ac8606Spatrick if (is<DynamicAllocLValue>())
86a9ac8606Spatrick return getDynamicAllocType();
87a9ac8606Spatrick
88a9ac8606Spatrick const Expr *Base = get<const Expr*>();
89a9ac8606Spatrick
90a9ac8606Spatrick // For a materialized temporary, the type of the temporary we materialized
91a9ac8606Spatrick // may not be the type of the expression.
92a9ac8606Spatrick if (const MaterializeTemporaryExpr *MTE =
93a9ac8606Spatrick clang::dyn_cast<MaterializeTemporaryExpr>(Base)) {
94a9ac8606Spatrick SmallVector<const Expr *, 2> CommaLHSs;
95a9ac8606Spatrick SmallVector<SubobjectAdjustment, 2> Adjustments;
96a9ac8606Spatrick const Expr *Temp = MTE->getSubExpr();
97a9ac8606Spatrick const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs,
98a9ac8606Spatrick Adjustments);
99a9ac8606Spatrick // Keep any cv-qualifiers from the reference if we generated a temporary
100a9ac8606Spatrick // for it directly. Otherwise use the type after adjustment.
101a9ac8606Spatrick if (!Adjustments.empty())
102a9ac8606Spatrick return Inner->getType();
103a9ac8606Spatrick }
104a9ac8606Spatrick
105a9ac8606Spatrick return Base->getType();
106a9ac8606Spatrick }
107a9ac8606Spatrick
getCallIndex() const108e5dd7070Spatrick unsigned APValue::LValueBase::getCallIndex() const {
109e5dd7070Spatrick return (is<TypeInfoLValue>() || is<DynamicAllocLValue>()) ? 0
110e5dd7070Spatrick : Local.CallIndex;
111e5dd7070Spatrick }
112e5dd7070Spatrick
getVersion() const113e5dd7070Spatrick unsigned APValue::LValueBase::getVersion() const {
114e5dd7070Spatrick return (is<TypeInfoLValue>() || is<DynamicAllocLValue>()) ? 0 : Local.Version;
115e5dd7070Spatrick }
116e5dd7070Spatrick
getTypeInfoType() const117e5dd7070Spatrick QualType APValue::LValueBase::getTypeInfoType() const {
118e5dd7070Spatrick assert(is<TypeInfoLValue>() && "not a type_info lvalue");
119e5dd7070Spatrick return QualType::getFromOpaquePtr(TypeInfoType);
120e5dd7070Spatrick }
121e5dd7070Spatrick
getDynamicAllocType() const122e5dd7070Spatrick QualType APValue::LValueBase::getDynamicAllocType() const {
123e5dd7070Spatrick assert(is<DynamicAllocLValue>() && "not a dynamic allocation lvalue");
124e5dd7070Spatrick return QualType::getFromOpaquePtr(DynamicAllocType);
125e5dd7070Spatrick }
126e5dd7070Spatrick
Profile(llvm::FoldingSetNodeID & ID) const127a9ac8606Spatrick void APValue::LValueBase::Profile(llvm::FoldingSetNodeID &ID) const {
128a9ac8606Spatrick ID.AddPointer(Ptr.getOpaqueValue());
129a9ac8606Spatrick if (is<TypeInfoLValue>() || is<DynamicAllocLValue>())
130a9ac8606Spatrick return;
131a9ac8606Spatrick ID.AddInteger(Local.CallIndex);
132a9ac8606Spatrick ID.AddInteger(Local.Version);
133a9ac8606Spatrick }
134a9ac8606Spatrick
135e5dd7070Spatrick namespace clang {
operator ==(const APValue::LValueBase & LHS,const APValue::LValueBase & RHS)136e5dd7070Spatrick bool operator==(const APValue::LValueBase &LHS,
137e5dd7070Spatrick const APValue::LValueBase &RHS) {
138e5dd7070Spatrick if (LHS.Ptr != RHS.Ptr)
139e5dd7070Spatrick return false;
140a9ac8606Spatrick if (LHS.is<TypeInfoLValue>() || LHS.is<DynamicAllocLValue>())
141e5dd7070Spatrick return true;
142e5dd7070Spatrick return LHS.Local.CallIndex == RHS.Local.CallIndex &&
143e5dd7070Spatrick LHS.Local.Version == RHS.Local.Version;
144e5dd7070Spatrick }
145e5dd7070Spatrick }
146e5dd7070Spatrick
LValuePathEntry(BaseOrMemberType BaseOrMember)147a9ac8606Spatrick APValue::LValuePathEntry::LValuePathEntry(BaseOrMemberType BaseOrMember) {
148a9ac8606Spatrick if (const Decl *D = BaseOrMember.getPointer())
149a9ac8606Spatrick BaseOrMember.setPointer(D->getCanonicalDecl());
150a9ac8606Spatrick Value = reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue());
151a9ac8606Spatrick }
152a9ac8606Spatrick
Profile(llvm::FoldingSetNodeID & ID) const153a9ac8606Spatrick void APValue::LValuePathEntry::Profile(llvm::FoldingSetNodeID &ID) const {
154a9ac8606Spatrick ID.AddInteger(Value);
155a9ac8606Spatrick }
156a9ac8606Spatrick
LValuePathSerializationHelper(ArrayRef<LValuePathEntry> Path,QualType ElemTy)157a9ac8606Spatrick APValue::LValuePathSerializationHelper::LValuePathSerializationHelper(
158a9ac8606Spatrick ArrayRef<LValuePathEntry> Path, QualType ElemTy)
159*12c85518Srobert : Ty((const void *)ElemTy.getTypePtrOrNull()), Path(Path) {}
160a9ac8606Spatrick
getType()161a9ac8606Spatrick QualType APValue::LValuePathSerializationHelper::getType() {
162*12c85518Srobert return QualType::getFromOpaquePtr(Ty);
163a9ac8606Spatrick }
164a9ac8606Spatrick
165e5dd7070Spatrick namespace {
166e5dd7070Spatrick struct LVBase {
167e5dd7070Spatrick APValue::LValueBase Base;
168e5dd7070Spatrick CharUnits Offset;
169e5dd7070Spatrick unsigned PathLength;
170e5dd7070Spatrick bool IsNullPtr : 1;
171e5dd7070Spatrick bool IsOnePastTheEnd : 1;
172e5dd7070Spatrick };
173e5dd7070Spatrick }
174e5dd7070Spatrick
getOpaqueValue() const175e5dd7070Spatrick void *APValue::LValueBase::getOpaqueValue() const {
176e5dd7070Spatrick return Ptr.getOpaqueValue();
177e5dd7070Spatrick }
178e5dd7070Spatrick
isNull() const179e5dd7070Spatrick bool APValue::LValueBase::isNull() const {
180e5dd7070Spatrick return Ptr.isNull();
181e5dd7070Spatrick }
182e5dd7070Spatrick
operator bool() const183e5dd7070Spatrick APValue::LValueBase::operator bool () const {
184e5dd7070Spatrick return static_cast<bool>(Ptr);
185e5dd7070Spatrick }
186e5dd7070Spatrick
187e5dd7070Spatrick clang::APValue::LValueBase
getEmptyKey()188e5dd7070Spatrick llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
189a9ac8606Spatrick clang::APValue::LValueBase B;
190a9ac8606Spatrick B.Ptr = DenseMapInfo<const ValueDecl*>::getEmptyKey();
191a9ac8606Spatrick return B;
192e5dd7070Spatrick }
193e5dd7070Spatrick
194e5dd7070Spatrick clang::APValue::LValueBase
getTombstoneKey()195e5dd7070Spatrick llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
196a9ac8606Spatrick clang::APValue::LValueBase B;
197a9ac8606Spatrick B.Ptr = DenseMapInfo<const ValueDecl*>::getTombstoneKey();
198a9ac8606Spatrick return B;
199e5dd7070Spatrick }
200e5dd7070Spatrick
201e5dd7070Spatrick namespace clang {
hash_value(const APValue::LValueBase & Base)202e5dd7070Spatrick llvm::hash_code hash_value(const APValue::LValueBase &Base) {
203e5dd7070Spatrick if (Base.is<TypeInfoLValue>() || Base.is<DynamicAllocLValue>())
204e5dd7070Spatrick return llvm::hash_value(Base.getOpaqueValue());
205e5dd7070Spatrick return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(),
206e5dd7070Spatrick Base.getVersion());
207e5dd7070Spatrick }
208e5dd7070Spatrick }
209e5dd7070Spatrick
getHashValue(const clang::APValue::LValueBase & Base)210e5dd7070Spatrick unsigned llvm::DenseMapInfo<clang::APValue::LValueBase>::getHashValue(
211e5dd7070Spatrick const clang::APValue::LValueBase &Base) {
212e5dd7070Spatrick return hash_value(Base);
213e5dd7070Spatrick }
214e5dd7070Spatrick
isEqual(const clang::APValue::LValueBase & LHS,const clang::APValue::LValueBase & RHS)215e5dd7070Spatrick bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual(
216e5dd7070Spatrick const clang::APValue::LValueBase &LHS,
217e5dd7070Spatrick const clang::APValue::LValueBase &RHS) {
218e5dd7070Spatrick return LHS == RHS;
219e5dd7070Spatrick }
220e5dd7070Spatrick
221e5dd7070Spatrick struct APValue::LV : LVBase {
222e5dd7070Spatrick static const unsigned InlinePathSpace =
223e5dd7070Spatrick (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
224e5dd7070Spatrick
225e5dd7070Spatrick /// Path - The sequence of base classes, fields and array indices to follow to
226e5dd7070Spatrick /// walk from Base to the subobject. When performing GCC-style folding, there
227e5dd7070Spatrick /// may not be such a path.
228e5dd7070Spatrick union {
229e5dd7070Spatrick LValuePathEntry Path[InlinePathSpace];
230e5dd7070Spatrick LValuePathEntry *PathPtr;
231e5dd7070Spatrick };
232e5dd7070Spatrick
LVAPValue::LV233e5dd7070Spatrick LV() { PathLength = (unsigned)-1; }
~LVAPValue::LV234e5dd7070Spatrick ~LV() { resizePath(0); }
235e5dd7070Spatrick
resizePathAPValue::LV236e5dd7070Spatrick void resizePath(unsigned Length) {
237e5dd7070Spatrick if (Length == PathLength)
238e5dd7070Spatrick return;
239e5dd7070Spatrick if (hasPathPtr())
240e5dd7070Spatrick delete [] PathPtr;
241e5dd7070Spatrick PathLength = Length;
242e5dd7070Spatrick if (hasPathPtr())
243e5dd7070Spatrick PathPtr = new LValuePathEntry[Length];
244e5dd7070Spatrick }
245e5dd7070Spatrick
hasPathAPValue::LV246e5dd7070Spatrick bool hasPath() const { return PathLength != (unsigned)-1; }
hasPathPtrAPValue::LV247e5dd7070Spatrick bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }
248e5dd7070Spatrick
getPathAPValue::LV249e5dd7070Spatrick LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }
getPathAPValue::LV250e5dd7070Spatrick const LValuePathEntry *getPath() const {
251e5dd7070Spatrick return hasPathPtr() ? PathPtr : Path;
252e5dd7070Spatrick }
253e5dd7070Spatrick };
254e5dd7070Spatrick
255e5dd7070Spatrick namespace {
256e5dd7070Spatrick struct MemberPointerBase {
257e5dd7070Spatrick llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember;
258e5dd7070Spatrick unsigned PathLength;
259e5dd7070Spatrick };
260e5dd7070Spatrick }
261e5dd7070Spatrick
262e5dd7070Spatrick struct APValue::MemberPointerData : MemberPointerBase {
263e5dd7070Spatrick static const unsigned InlinePathSpace =
264e5dd7070Spatrick (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*);
265e5dd7070Spatrick typedef const CXXRecordDecl *PathElem;
266e5dd7070Spatrick union {
267e5dd7070Spatrick PathElem Path[InlinePathSpace];
268e5dd7070Spatrick PathElem *PathPtr;
269e5dd7070Spatrick };
270e5dd7070Spatrick
MemberPointerDataAPValue::MemberPointerData271e5dd7070Spatrick MemberPointerData() { PathLength = 0; }
~MemberPointerDataAPValue::MemberPointerData272e5dd7070Spatrick ~MemberPointerData() { resizePath(0); }
273e5dd7070Spatrick
resizePathAPValue::MemberPointerData274e5dd7070Spatrick void resizePath(unsigned Length) {
275e5dd7070Spatrick if (Length == PathLength)
276e5dd7070Spatrick return;
277e5dd7070Spatrick if (hasPathPtr())
278e5dd7070Spatrick delete [] PathPtr;
279e5dd7070Spatrick PathLength = Length;
280e5dd7070Spatrick if (hasPathPtr())
281e5dd7070Spatrick PathPtr = new PathElem[Length];
282e5dd7070Spatrick }
283e5dd7070Spatrick
hasPathPtrAPValue::MemberPointerData284e5dd7070Spatrick bool hasPathPtr() const { return PathLength > InlinePathSpace; }
285e5dd7070Spatrick
getPathAPValue::MemberPointerData286e5dd7070Spatrick PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; }
getPathAPValue::MemberPointerData287e5dd7070Spatrick const PathElem *getPath() const {
288e5dd7070Spatrick return hasPathPtr() ? PathPtr : Path;
289e5dd7070Spatrick }
290e5dd7070Spatrick };
291e5dd7070Spatrick
292e5dd7070Spatrick // FIXME: Reduce the malloc traffic here.
293e5dd7070Spatrick
Arr(unsigned NumElts,unsigned Size)294e5dd7070Spatrick APValue::Arr::Arr(unsigned NumElts, unsigned Size) :
295e5dd7070Spatrick Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]),
296e5dd7070Spatrick NumElts(NumElts), ArrSize(Size) {}
~Arr()297e5dd7070Spatrick APValue::Arr::~Arr() { delete [] Elts; }
298e5dd7070Spatrick
StructData(unsigned NumBases,unsigned NumFields)299e5dd7070Spatrick APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) :
300e5dd7070Spatrick Elts(new APValue[NumBases+NumFields]),
301e5dd7070Spatrick NumBases(NumBases), NumFields(NumFields) {}
~StructData()302e5dd7070Spatrick APValue::StructData::~StructData() {
303e5dd7070Spatrick delete [] Elts;
304e5dd7070Spatrick }
305e5dd7070Spatrick
UnionData()306e5dd7070Spatrick APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {}
~UnionData()307e5dd7070Spatrick APValue::UnionData::~UnionData () {
308e5dd7070Spatrick delete Value;
309e5dd7070Spatrick }
310e5dd7070Spatrick
APValue(const APValue & RHS)311e5dd7070Spatrick APValue::APValue(const APValue &RHS) : Kind(None) {
312e5dd7070Spatrick switch (RHS.getKind()) {
313e5dd7070Spatrick case None:
314e5dd7070Spatrick case Indeterminate:
315e5dd7070Spatrick Kind = RHS.getKind();
316e5dd7070Spatrick break;
317e5dd7070Spatrick case Int:
318e5dd7070Spatrick MakeInt();
319e5dd7070Spatrick setInt(RHS.getInt());
320e5dd7070Spatrick break;
321e5dd7070Spatrick case Float:
322e5dd7070Spatrick MakeFloat();
323e5dd7070Spatrick setFloat(RHS.getFloat());
324e5dd7070Spatrick break;
325e5dd7070Spatrick case FixedPoint: {
326e5dd7070Spatrick APFixedPoint FXCopy = RHS.getFixedPoint();
327e5dd7070Spatrick MakeFixedPoint(std::move(FXCopy));
328e5dd7070Spatrick break;
329e5dd7070Spatrick }
330e5dd7070Spatrick case Vector:
331e5dd7070Spatrick MakeVector();
332a9ac8606Spatrick setVector(((const Vec *)(const char *)&RHS.Data)->Elts,
333e5dd7070Spatrick RHS.getVectorLength());
334e5dd7070Spatrick break;
335e5dd7070Spatrick case ComplexInt:
336e5dd7070Spatrick MakeComplexInt();
337e5dd7070Spatrick setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
338e5dd7070Spatrick break;
339e5dd7070Spatrick case ComplexFloat:
340e5dd7070Spatrick MakeComplexFloat();
341e5dd7070Spatrick setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
342e5dd7070Spatrick break;
343e5dd7070Spatrick case LValue:
344e5dd7070Spatrick MakeLValue();
345e5dd7070Spatrick if (RHS.hasLValuePath())
346e5dd7070Spatrick setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
347e5dd7070Spatrick RHS.isLValueOnePastTheEnd(), RHS.isNullPointer());
348e5dd7070Spatrick else
349e5dd7070Spatrick setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
350e5dd7070Spatrick RHS.isNullPointer());
351e5dd7070Spatrick break;
352e5dd7070Spatrick case Array:
353e5dd7070Spatrick MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
354e5dd7070Spatrick for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)
355e5dd7070Spatrick getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);
356e5dd7070Spatrick if (RHS.hasArrayFiller())
357e5dd7070Spatrick getArrayFiller() = RHS.getArrayFiller();
358e5dd7070Spatrick break;
359e5dd7070Spatrick case Struct:
360e5dd7070Spatrick MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());
361e5dd7070Spatrick for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I)
362e5dd7070Spatrick getStructBase(I) = RHS.getStructBase(I);
363e5dd7070Spatrick for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I)
364e5dd7070Spatrick getStructField(I) = RHS.getStructField(I);
365e5dd7070Spatrick break;
366e5dd7070Spatrick case Union:
367e5dd7070Spatrick MakeUnion();
368e5dd7070Spatrick setUnion(RHS.getUnionField(), RHS.getUnionValue());
369e5dd7070Spatrick break;
370e5dd7070Spatrick case MemberPointer:
371e5dd7070Spatrick MakeMemberPointer(RHS.getMemberPointerDecl(),
372e5dd7070Spatrick RHS.isMemberPointerToDerivedMember(),
373e5dd7070Spatrick RHS.getMemberPointerPath());
374e5dd7070Spatrick break;
375e5dd7070Spatrick case AddrLabelDiff:
376e5dd7070Spatrick MakeAddrLabelDiff();
377e5dd7070Spatrick setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS());
378e5dd7070Spatrick break;
379e5dd7070Spatrick }
380e5dd7070Spatrick }
381e5dd7070Spatrick
APValue(APValue && RHS)382a9ac8606Spatrick APValue::APValue(APValue &&RHS) : Kind(RHS.Kind), Data(RHS.Data) {
383a9ac8606Spatrick RHS.Kind = None;
384a9ac8606Spatrick }
385a9ac8606Spatrick
operator =(const APValue & RHS)386a9ac8606Spatrick APValue &APValue::operator=(const APValue &RHS) {
387a9ac8606Spatrick if (this != &RHS)
388a9ac8606Spatrick *this = APValue(RHS);
389a9ac8606Spatrick return *this;
390a9ac8606Spatrick }
391a9ac8606Spatrick
operator =(APValue && RHS)392a9ac8606Spatrick APValue &APValue::operator=(APValue &&RHS) {
393a9ac8606Spatrick if (Kind != None && Kind != Indeterminate)
394a9ac8606Spatrick DestroyDataAndMakeUninit();
395a9ac8606Spatrick Kind = RHS.Kind;
396a9ac8606Spatrick Data = RHS.Data;
397a9ac8606Spatrick RHS.Kind = None;
398a9ac8606Spatrick return *this;
399a9ac8606Spatrick }
400a9ac8606Spatrick
DestroyDataAndMakeUninit()401e5dd7070Spatrick void APValue::DestroyDataAndMakeUninit() {
402e5dd7070Spatrick if (Kind == Int)
403a9ac8606Spatrick ((APSInt *)(char *)&Data)->~APSInt();
404e5dd7070Spatrick else if (Kind == Float)
405a9ac8606Spatrick ((APFloat *)(char *)&Data)->~APFloat();
406e5dd7070Spatrick else if (Kind == FixedPoint)
407a9ac8606Spatrick ((APFixedPoint *)(char *)&Data)->~APFixedPoint();
408e5dd7070Spatrick else if (Kind == Vector)
409a9ac8606Spatrick ((Vec *)(char *)&Data)->~Vec();
410e5dd7070Spatrick else if (Kind == ComplexInt)
411a9ac8606Spatrick ((ComplexAPSInt *)(char *)&Data)->~ComplexAPSInt();
412e5dd7070Spatrick else if (Kind == ComplexFloat)
413a9ac8606Spatrick ((ComplexAPFloat *)(char *)&Data)->~ComplexAPFloat();
414e5dd7070Spatrick else if (Kind == LValue)
415a9ac8606Spatrick ((LV *)(char *)&Data)->~LV();
416e5dd7070Spatrick else if (Kind == Array)
417a9ac8606Spatrick ((Arr *)(char *)&Data)->~Arr();
418e5dd7070Spatrick else if (Kind == Struct)
419a9ac8606Spatrick ((StructData *)(char *)&Data)->~StructData();
420e5dd7070Spatrick else if (Kind == Union)
421a9ac8606Spatrick ((UnionData *)(char *)&Data)->~UnionData();
422e5dd7070Spatrick else if (Kind == MemberPointer)
423a9ac8606Spatrick ((MemberPointerData *)(char *)&Data)->~MemberPointerData();
424e5dd7070Spatrick else if (Kind == AddrLabelDiff)
425a9ac8606Spatrick ((AddrLabelDiffData *)(char *)&Data)->~AddrLabelDiffData();
426e5dd7070Spatrick Kind = None;
427e5dd7070Spatrick }
428e5dd7070Spatrick
needsCleanup() const429e5dd7070Spatrick bool APValue::needsCleanup() const {
430e5dd7070Spatrick switch (getKind()) {
431e5dd7070Spatrick case None:
432e5dd7070Spatrick case Indeterminate:
433e5dd7070Spatrick case AddrLabelDiff:
434e5dd7070Spatrick return false;
435e5dd7070Spatrick case Struct:
436e5dd7070Spatrick case Union:
437e5dd7070Spatrick case Array:
438e5dd7070Spatrick case Vector:
439e5dd7070Spatrick return true;
440e5dd7070Spatrick case Int:
441e5dd7070Spatrick return getInt().needsCleanup();
442e5dd7070Spatrick case Float:
443e5dd7070Spatrick return getFloat().needsCleanup();
444e5dd7070Spatrick case FixedPoint:
445e5dd7070Spatrick return getFixedPoint().getValue().needsCleanup();
446e5dd7070Spatrick case ComplexFloat:
447e5dd7070Spatrick assert(getComplexFloatImag().needsCleanup() ==
448e5dd7070Spatrick getComplexFloatReal().needsCleanup() &&
449e5dd7070Spatrick "In _Complex float types, real and imaginary values always have the "
450e5dd7070Spatrick "same size.");
451e5dd7070Spatrick return getComplexFloatReal().needsCleanup();
452e5dd7070Spatrick case ComplexInt:
453e5dd7070Spatrick assert(getComplexIntImag().needsCleanup() ==
454e5dd7070Spatrick getComplexIntReal().needsCleanup() &&
455e5dd7070Spatrick "In _Complex int types, real and imaginary values must have the "
456e5dd7070Spatrick "same size.");
457e5dd7070Spatrick return getComplexIntReal().needsCleanup();
458e5dd7070Spatrick case LValue:
459a9ac8606Spatrick return reinterpret_cast<const LV *>(&Data)->hasPathPtr();
460e5dd7070Spatrick case MemberPointer:
461a9ac8606Spatrick return reinterpret_cast<const MemberPointerData *>(&Data)->hasPathPtr();
462e5dd7070Spatrick }
463e5dd7070Spatrick llvm_unreachable("Unknown APValue kind!");
464e5dd7070Spatrick }
465e5dd7070Spatrick
swap(APValue & RHS)466e5dd7070Spatrick void APValue::swap(APValue &RHS) {
467e5dd7070Spatrick std::swap(Kind, RHS.Kind);
468a9ac8606Spatrick std::swap(Data, RHS.Data);
469a9ac8606Spatrick }
470a9ac8606Spatrick
471a9ac8606Spatrick /// Profile the value of an APInt, excluding its bit-width.
profileIntValue(llvm::FoldingSetNodeID & ID,const llvm::APInt & V)472a9ac8606Spatrick static void profileIntValue(llvm::FoldingSetNodeID &ID, const llvm::APInt &V) {
473a9ac8606Spatrick for (unsigned I = 0, N = V.getBitWidth(); I < N; I += 32)
474a9ac8606Spatrick ID.AddInteger((uint32_t)V.extractBitsAsZExtValue(std::min(32u, N - I), I));
475a9ac8606Spatrick }
476a9ac8606Spatrick
Profile(llvm::FoldingSetNodeID & ID) const477a9ac8606Spatrick void APValue::Profile(llvm::FoldingSetNodeID &ID) const {
478a9ac8606Spatrick // Note that our profiling assumes that only APValues of the same type are
479a9ac8606Spatrick // ever compared. As a result, we don't consider collisions that could only
480a9ac8606Spatrick // happen if the types are different. (For example, structs with different
481a9ac8606Spatrick // numbers of members could profile the same.)
482a9ac8606Spatrick
483a9ac8606Spatrick ID.AddInteger(Kind);
484a9ac8606Spatrick
485a9ac8606Spatrick switch (Kind) {
486a9ac8606Spatrick case None:
487a9ac8606Spatrick case Indeterminate:
488a9ac8606Spatrick return;
489a9ac8606Spatrick
490a9ac8606Spatrick case AddrLabelDiff:
491a9ac8606Spatrick ID.AddPointer(getAddrLabelDiffLHS()->getLabel()->getCanonicalDecl());
492a9ac8606Spatrick ID.AddPointer(getAddrLabelDiffRHS()->getLabel()->getCanonicalDecl());
493a9ac8606Spatrick return;
494a9ac8606Spatrick
495a9ac8606Spatrick case Struct:
496a9ac8606Spatrick for (unsigned I = 0, N = getStructNumBases(); I != N; ++I)
497a9ac8606Spatrick getStructBase(I).Profile(ID);
498a9ac8606Spatrick for (unsigned I = 0, N = getStructNumFields(); I != N; ++I)
499a9ac8606Spatrick getStructField(I).Profile(ID);
500a9ac8606Spatrick return;
501a9ac8606Spatrick
502a9ac8606Spatrick case Union:
503a9ac8606Spatrick if (!getUnionField()) {
504a9ac8606Spatrick ID.AddInteger(0);
505a9ac8606Spatrick return;
506a9ac8606Spatrick }
507a9ac8606Spatrick ID.AddInteger(getUnionField()->getFieldIndex() + 1);
508a9ac8606Spatrick getUnionValue().Profile(ID);
509a9ac8606Spatrick return;
510a9ac8606Spatrick
511a9ac8606Spatrick case Array: {
512a9ac8606Spatrick if (getArraySize() == 0)
513a9ac8606Spatrick return;
514a9ac8606Spatrick
515a9ac8606Spatrick // The profile should not depend on whether the array is expanded or
516a9ac8606Spatrick // not, but we don't want to profile the array filler many times for
517a9ac8606Spatrick // a large array. So treat all equal trailing elements as the filler.
518a9ac8606Spatrick // Elements are profiled in reverse order to support this, and the
519a9ac8606Spatrick // first profiled element is followed by a count. For example:
520a9ac8606Spatrick //
521a9ac8606Spatrick // ['a', 'c', 'x', 'x', 'x'] is profiled as
522a9ac8606Spatrick // [5, 'x', 3, 'c', 'a']
523a9ac8606Spatrick llvm::FoldingSetNodeID FillerID;
524a9ac8606Spatrick (hasArrayFiller() ? getArrayFiller()
525a9ac8606Spatrick : getArrayInitializedElt(getArrayInitializedElts() - 1))
526a9ac8606Spatrick .Profile(FillerID);
527a9ac8606Spatrick ID.AddNodeID(FillerID);
528a9ac8606Spatrick unsigned NumFillers = getArraySize() - getArrayInitializedElts();
529a9ac8606Spatrick unsigned N = getArrayInitializedElts();
530a9ac8606Spatrick
531a9ac8606Spatrick // Count the number of elements equal to the last one. This loop ends
532a9ac8606Spatrick // by adding an integer indicating the number of such elements, with
533a9ac8606Spatrick // N set to the number of elements left to profile.
534a9ac8606Spatrick while (true) {
535a9ac8606Spatrick if (N == 0) {
536a9ac8606Spatrick // All elements are fillers.
537a9ac8606Spatrick assert(NumFillers == getArraySize());
538a9ac8606Spatrick ID.AddInteger(NumFillers);
539a9ac8606Spatrick break;
540a9ac8606Spatrick }
541a9ac8606Spatrick
542a9ac8606Spatrick // No need to check if the last element is equal to the last
543a9ac8606Spatrick // element.
544a9ac8606Spatrick if (N != getArraySize()) {
545a9ac8606Spatrick llvm::FoldingSetNodeID ElemID;
546a9ac8606Spatrick getArrayInitializedElt(N - 1).Profile(ElemID);
547a9ac8606Spatrick if (ElemID != FillerID) {
548a9ac8606Spatrick ID.AddInteger(NumFillers);
549a9ac8606Spatrick ID.AddNodeID(ElemID);
550a9ac8606Spatrick --N;
551a9ac8606Spatrick break;
552a9ac8606Spatrick }
553a9ac8606Spatrick }
554a9ac8606Spatrick
555a9ac8606Spatrick // This is a filler.
556a9ac8606Spatrick ++NumFillers;
557a9ac8606Spatrick --N;
558a9ac8606Spatrick }
559a9ac8606Spatrick
560a9ac8606Spatrick // Emit the remaining elements.
561a9ac8606Spatrick for (; N != 0; --N)
562a9ac8606Spatrick getArrayInitializedElt(N - 1).Profile(ID);
563a9ac8606Spatrick return;
564a9ac8606Spatrick }
565a9ac8606Spatrick
566a9ac8606Spatrick case Vector:
567a9ac8606Spatrick for (unsigned I = 0, N = getVectorLength(); I != N; ++I)
568a9ac8606Spatrick getVectorElt(I).Profile(ID);
569a9ac8606Spatrick return;
570a9ac8606Spatrick
571a9ac8606Spatrick case Int:
572a9ac8606Spatrick profileIntValue(ID, getInt());
573a9ac8606Spatrick return;
574a9ac8606Spatrick
575a9ac8606Spatrick case Float:
576a9ac8606Spatrick profileIntValue(ID, getFloat().bitcastToAPInt());
577a9ac8606Spatrick return;
578a9ac8606Spatrick
579a9ac8606Spatrick case FixedPoint:
580a9ac8606Spatrick profileIntValue(ID, getFixedPoint().getValue());
581a9ac8606Spatrick return;
582a9ac8606Spatrick
583a9ac8606Spatrick case ComplexFloat:
584a9ac8606Spatrick profileIntValue(ID, getComplexFloatReal().bitcastToAPInt());
585a9ac8606Spatrick profileIntValue(ID, getComplexFloatImag().bitcastToAPInt());
586a9ac8606Spatrick return;
587a9ac8606Spatrick
588a9ac8606Spatrick case ComplexInt:
589a9ac8606Spatrick profileIntValue(ID, getComplexIntReal());
590a9ac8606Spatrick profileIntValue(ID, getComplexIntImag());
591a9ac8606Spatrick return;
592a9ac8606Spatrick
593a9ac8606Spatrick case LValue:
594a9ac8606Spatrick getLValueBase().Profile(ID);
595a9ac8606Spatrick ID.AddInteger(getLValueOffset().getQuantity());
596a9ac8606Spatrick ID.AddInteger((isNullPointer() ? 1 : 0) |
597a9ac8606Spatrick (isLValueOnePastTheEnd() ? 2 : 0) |
598a9ac8606Spatrick (hasLValuePath() ? 4 : 0));
599a9ac8606Spatrick if (hasLValuePath()) {
600a9ac8606Spatrick ID.AddInteger(getLValuePath().size());
601a9ac8606Spatrick // For uniqueness, we only need to profile the entries corresponding
602a9ac8606Spatrick // to union members, but we don't have the type here so we don't know
603a9ac8606Spatrick // how to interpret the entries.
604a9ac8606Spatrick for (LValuePathEntry E : getLValuePath())
605a9ac8606Spatrick E.Profile(ID);
606a9ac8606Spatrick }
607a9ac8606Spatrick return;
608a9ac8606Spatrick
609a9ac8606Spatrick case MemberPointer:
610a9ac8606Spatrick ID.AddPointer(getMemberPointerDecl());
611a9ac8606Spatrick ID.AddInteger(isMemberPointerToDerivedMember());
612a9ac8606Spatrick for (const CXXRecordDecl *D : getMemberPointerPath())
613a9ac8606Spatrick ID.AddPointer(D);
614a9ac8606Spatrick return;
615a9ac8606Spatrick }
616a9ac8606Spatrick
617a9ac8606Spatrick llvm_unreachable("Unknown APValue kind!");
618e5dd7070Spatrick }
619e5dd7070Spatrick
GetApproxValue(const llvm::APFloat & F)620e5dd7070Spatrick static double GetApproxValue(const llvm::APFloat &F) {
621e5dd7070Spatrick llvm::APFloat V = F;
622e5dd7070Spatrick bool ignored;
623e5dd7070Spatrick V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
624e5dd7070Spatrick &ignored);
625e5dd7070Spatrick return V.convertToDouble();
626e5dd7070Spatrick }
627e5dd7070Spatrick
TryPrintAsStringLiteral(raw_ostream & Out,const PrintingPolicy & Policy,const ArrayType * ATy,ArrayRef<APValue> Inits)628*12c85518Srobert static bool TryPrintAsStringLiteral(raw_ostream &Out,
629*12c85518Srobert const PrintingPolicy &Policy,
630*12c85518Srobert const ArrayType *ATy,
631*12c85518Srobert ArrayRef<APValue> Inits) {
632*12c85518Srobert if (Inits.empty())
633*12c85518Srobert return false;
634*12c85518Srobert
635*12c85518Srobert QualType Ty = ATy->getElementType();
636*12c85518Srobert if (!Ty->isAnyCharacterType())
637*12c85518Srobert return false;
638*12c85518Srobert
639*12c85518Srobert // Nothing we can do about a sequence that is not null-terminated
640*12c85518Srobert if (!Inits.back().isInt() || !Inits.back().getInt().isZero())
641*12c85518Srobert return false;
642*12c85518Srobert
643*12c85518Srobert Inits = Inits.drop_back();
644*12c85518Srobert
645*12c85518Srobert llvm::SmallString<40> Buf;
646*12c85518Srobert Buf.push_back('"');
647*12c85518Srobert
648*12c85518Srobert // Better than printing a two-digit sequence of 10 integers.
649*12c85518Srobert constexpr size_t MaxN = 36;
650*12c85518Srobert StringRef Ellipsis;
651*12c85518Srobert if (Inits.size() > MaxN && !Policy.EntireContentsOfLargeArray) {
652*12c85518Srobert Ellipsis = "[...]";
653*12c85518Srobert Inits =
654*12c85518Srobert Inits.take_front(std::min(MaxN - Ellipsis.size() / 2, Inits.size()));
655*12c85518Srobert }
656*12c85518Srobert
657*12c85518Srobert for (auto &Val : Inits) {
658*12c85518Srobert if (!Val.isInt())
659*12c85518Srobert return false;
660*12c85518Srobert int64_t Char64 = Val.getInt().getExtValue();
661*12c85518Srobert if (!isASCII(Char64))
662*12c85518Srobert return false; // Bye bye, see you in integers.
663*12c85518Srobert auto Ch = static_cast<unsigned char>(Char64);
664*12c85518Srobert // The diagnostic message is 'quoted'
665*12c85518Srobert StringRef Escaped = escapeCStyle<EscapeChar::SingleAndDouble>(Ch);
666*12c85518Srobert if (Escaped.empty()) {
667*12c85518Srobert if (!isPrintable(Ch))
668*12c85518Srobert return false;
669*12c85518Srobert Buf.emplace_back(Ch);
670*12c85518Srobert } else {
671*12c85518Srobert Buf.append(Escaped);
672*12c85518Srobert }
673*12c85518Srobert }
674*12c85518Srobert
675*12c85518Srobert Buf.append(Ellipsis);
676*12c85518Srobert Buf.push_back('"');
677*12c85518Srobert
678*12c85518Srobert if (Ty->isWideCharType())
679*12c85518Srobert Out << 'L';
680*12c85518Srobert else if (Ty->isChar8Type())
681*12c85518Srobert Out << "u8";
682*12c85518Srobert else if (Ty->isChar16Type())
683*12c85518Srobert Out << 'u';
684*12c85518Srobert else if (Ty->isChar32Type())
685*12c85518Srobert Out << 'U';
686*12c85518Srobert
687*12c85518Srobert Out << Buf;
688*12c85518Srobert return true;
689*12c85518Srobert }
690*12c85518Srobert
printPretty(raw_ostream & Out,const ASTContext & Ctx,QualType Ty) const691e5dd7070Spatrick void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx,
692e5dd7070Spatrick QualType Ty) const {
693a9ac8606Spatrick printPretty(Out, Ctx.getPrintingPolicy(), Ty, &Ctx);
694a9ac8606Spatrick }
695a9ac8606Spatrick
printPretty(raw_ostream & Out,const PrintingPolicy & Policy,QualType Ty,const ASTContext * Ctx) const696a9ac8606Spatrick void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy,
697a9ac8606Spatrick QualType Ty, const ASTContext *Ctx) const {
698a9ac8606Spatrick // There are no objects of type 'void', but values of this type can be
699a9ac8606Spatrick // returned from functions.
700a9ac8606Spatrick if (Ty->isVoidType()) {
701a9ac8606Spatrick Out << "void()";
702a9ac8606Spatrick return;
703a9ac8606Spatrick }
704a9ac8606Spatrick
705e5dd7070Spatrick switch (getKind()) {
706e5dd7070Spatrick case APValue::None:
707e5dd7070Spatrick Out << "<out of lifetime>";
708e5dd7070Spatrick return;
709e5dd7070Spatrick case APValue::Indeterminate:
710e5dd7070Spatrick Out << "<uninitialized>";
711e5dd7070Spatrick return;
712e5dd7070Spatrick case APValue::Int:
713e5dd7070Spatrick if (Ty->isBooleanType())
714e5dd7070Spatrick Out << (getInt().getBoolValue() ? "true" : "false");
715e5dd7070Spatrick else
716e5dd7070Spatrick Out << getInt();
717e5dd7070Spatrick return;
718e5dd7070Spatrick case APValue::Float:
719e5dd7070Spatrick Out << GetApproxValue(getFloat());
720e5dd7070Spatrick return;
721e5dd7070Spatrick case APValue::FixedPoint:
722e5dd7070Spatrick Out << getFixedPoint();
723e5dd7070Spatrick return;
724e5dd7070Spatrick case APValue::Vector: {
725e5dd7070Spatrick Out << '{';
726e5dd7070Spatrick QualType ElemTy = Ty->castAs<VectorType>()->getElementType();
727a9ac8606Spatrick getVectorElt(0).printPretty(Out, Policy, ElemTy, Ctx);
728e5dd7070Spatrick for (unsigned i = 1; i != getVectorLength(); ++i) {
729e5dd7070Spatrick Out << ", ";
730a9ac8606Spatrick getVectorElt(i).printPretty(Out, Policy, ElemTy, Ctx);
731e5dd7070Spatrick }
732e5dd7070Spatrick Out << '}';
733e5dd7070Spatrick return;
734e5dd7070Spatrick }
735e5dd7070Spatrick case APValue::ComplexInt:
736e5dd7070Spatrick Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";
737e5dd7070Spatrick return;
738e5dd7070Spatrick case APValue::ComplexFloat:
739e5dd7070Spatrick Out << GetApproxValue(getComplexFloatReal()) << "+"
740e5dd7070Spatrick << GetApproxValue(getComplexFloatImag()) << "i";
741e5dd7070Spatrick return;
742e5dd7070Spatrick case APValue::LValue: {
743e5dd7070Spatrick bool IsReference = Ty->isReferenceType();
744e5dd7070Spatrick QualType InnerTy
745e5dd7070Spatrick = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();
746e5dd7070Spatrick if (InnerTy.isNull())
747e5dd7070Spatrick InnerTy = Ty;
748e5dd7070Spatrick
749e5dd7070Spatrick LValueBase Base = getLValueBase();
750e5dd7070Spatrick if (!Base) {
751e5dd7070Spatrick if (isNullPointer()) {
752a9ac8606Spatrick Out << (Policy.Nullptr ? "nullptr" : "0");
753e5dd7070Spatrick } else if (IsReference) {
754a9ac8606Spatrick Out << "*(" << InnerTy.stream(Policy) << "*)"
755e5dd7070Spatrick << getLValueOffset().getQuantity();
756e5dd7070Spatrick } else {
757a9ac8606Spatrick Out << "(" << Ty.stream(Policy) << ")"
758e5dd7070Spatrick << getLValueOffset().getQuantity();
759e5dd7070Spatrick }
760e5dd7070Spatrick return;
761e5dd7070Spatrick }
762e5dd7070Spatrick
763e5dd7070Spatrick if (!hasLValuePath()) {
764e5dd7070Spatrick // No lvalue path: just print the offset.
765e5dd7070Spatrick CharUnits O = getLValueOffset();
766*12c85518Srobert CharUnits S = Ctx ? Ctx->getTypeSizeInCharsIfKnown(InnerTy).value_or(
767*12c85518Srobert CharUnits::Zero())
768*12c85518Srobert : CharUnits::Zero();
769e5dd7070Spatrick if (!O.isZero()) {
770e5dd7070Spatrick if (IsReference)
771e5dd7070Spatrick Out << "*(";
772a9ac8606Spatrick if (S.isZero() || O % S) {
773e5dd7070Spatrick Out << "(char*)";
774e5dd7070Spatrick S = CharUnits::One();
775e5dd7070Spatrick }
776e5dd7070Spatrick Out << '&';
777e5dd7070Spatrick } else if (!IsReference) {
778e5dd7070Spatrick Out << '&';
779e5dd7070Spatrick }
780e5dd7070Spatrick
781e5dd7070Spatrick if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
782e5dd7070Spatrick Out << *VD;
783e5dd7070Spatrick else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) {
784a9ac8606Spatrick TI.print(Out, Policy);
785e5dd7070Spatrick } else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) {
786e5dd7070Spatrick Out << "{*new "
787a9ac8606Spatrick << Base.getDynamicAllocType().stream(Policy) << "#"
788e5dd7070Spatrick << DA.getIndex() << "}";
789e5dd7070Spatrick } else {
790e5dd7070Spatrick assert(Base.get<const Expr *>() != nullptr &&
791e5dd7070Spatrick "Expecting non-null Expr");
792a9ac8606Spatrick Base.get<const Expr*>()->printPretty(Out, nullptr, Policy);
793e5dd7070Spatrick }
794e5dd7070Spatrick
795e5dd7070Spatrick if (!O.isZero()) {
796e5dd7070Spatrick Out << " + " << (O / S);
797e5dd7070Spatrick if (IsReference)
798e5dd7070Spatrick Out << ')';
799e5dd7070Spatrick }
800e5dd7070Spatrick return;
801e5dd7070Spatrick }
802e5dd7070Spatrick
803e5dd7070Spatrick // We have an lvalue path. Print it out nicely.
804e5dd7070Spatrick if (!IsReference)
805e5dd7070Spatrick Out << '&';
806e5dd7070Spatrick else if (isLValueOnePastTheEnd())
807e5dd7070Spatrick Out << "*(&";
808e5dd7070Spatrick
809a9ac8606Spatrick QualType ElemTy = Base.getType();
810e5dd7070Spatrick if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
811e5dd7070Spatrick Out << *VD;
812e5dd7070Spatrick } else if (TypeInfoLValue TI = Base.dyn_cast<TypeInfoLValue>()) {
813a9ac8606Spatrick TI.print(Out, Policy);
814e5dd7070Spatrick } else if (DynamicAllocLValue DA = Base.dyn_cast<DynamicAllocLValue>()) {
815a9ac8606Spatrick Out << "{*new " << Base.getDynamicAllocType().stream(Policy) << "#"
816e5dd7070Spatrick << DA.getIndex() << "}";
817e5dd7070Spatrick } else {
818e5dd7070Spatrick const Expr *E = Base.get<const Expr*>();
819e5dd7070Spatrick assert(E != nullptr && "Expecting non-null Expr");
820a9ac8606Spatrick E->printPretty(Out, nullptr, Policy);
821e5dd7070Spatrick }
822e5dd7070Spatrick
823e5dd7070Spatrick ArrayRef<LValuePathEntry> Path = getLValuePath();
824e5dd7070Spatrick const CXXRecordDecl *CastToBase = nullptr;
825e5dd7070Spatrick for (unsigned I = 0, N = Path.size(); I != N; ++I) {
826a9ac8606Spatrick if (ElemTy->isRecordType()) {
827e5dd7070Spatrick // The lvalue refers to a class type, so the next path entry is a base
828e5dd7070Spatrick // or member.
829e5dd7070Spatrick const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer();
830e5dd7070Spatrick if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
831e5dd7070Spatrick CastToBase = RD;
832a9ac8606Spatrick // Leave ElemTy referring to the most-derived class. The actual type
833a9ac8606Spatrick // doesn't matter except for array types.
834e5dd7070Spatrick } else {
835e5dd7070Spatrick const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
836e5dd7070Spatrick Out << ".";
837e5dd7070Spatrick if (CastToBase)
838e5dd7070Spatrick Out << *CastToBase << "::";
839e5dd7070Spatrick Out << *VD;
840e5dd7070Spatrick ElemTy = VD->getType();
841e5dd7070Spatrick }
842e5dd7070Spatrick } else {
843e5dd7070Spatrick // The lvalue must refer to an array.
844e5dd7070Spatrick Out << '[' << Path[I].getAsArrayIndex() << ']';
845a9ac8606Spatrick ElemTy = ElemTy->castAsArrayTypeUnsafe()->getElementType();
846e5dd7070Spatrick }
847e5dd7070Spatrick }
848e5dd7070Spatrick
849e5dd7070Spatrick // Handle formatting of one-past-the-end lvalues.
850e5dd7070Spatrick if (isLValueOnePastTheEnd()) {
851e5dd7070Spatrick // FIXME: If CastToBase is non-0, we should prefix the output with
852e5dd7070Spatrick // "(CastToBase*)".
853e5dd7070Spatrick Out << " + 1";
854e5dd7070Spatrick if (IsReference)
855e5dd7070Spatrick Out << ')';
856e5dd7070Spatrick }
857e5dd7070Spatrick return;
858e5dd7070Spatrick }
859e5dd7070Spatrick case APValue::Array: {
860a9ac8606Spatrick const ArrayType *AT = Ty->castAsArrayTypeUnsafe();
861*12c85518Srobert unsigned N = getArrayInitializedElts();
862*12c85518Srobert if (N != 0 && TryPrintAsStringLiteral(Out, Policy, AT,
863*12c85518Srobert {&getArrayInitializedElt(0), N}))
864*12c85518Srobert return;
865e5dd7070Spatrick QualType ElemTy = AT->getElementType();
866e5dd7070Spatrick Out << '{';
867*12c85518Srobert unsigned I = 0;
868*12c85518Srobert switch (N) {
869*12c85518Srobert case 0:
870*12c85518Srobert for (; I != N; ++I) {
871e5dd7070Spatrick Out << ", ";
872*12c85518Srobert if (I == 10 && !Policy.EntireContentsOfLargeArray) {
873*12c85518Srobert Out << "...}";
874*12c85518Srobert return;
875e5dd7070Spatrick }
876*12c85518Srobert [[fallthrough]];
877*12c85518Srobert default:
878a9ac8606Spatrick getArrayInitializedElt(I).printPretty(Out, Policy, ElemTy, Ctx);
879e5dd7070Spatrick }
880e5dd7070Spatrick }
881e5dd7070Spatrick Out << '}';
882e5dd7070Spatrick return;
883e5dd7070Spatrick }
884e5dd7070Spatrick case APValue::Struct: {
885e5dd7070Spatrick Out << '{';
886e5dd7070Spatrick const RecordDecl *RD = Ty->castAs<RecordType>()->getDecl();
887e5dd7070Spatrick bool First = true;
888e5dd7070Spatrick if (unsigned N = getStructNumBases()) {
889e5dd7070Spatrick const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
890e5dd7070Spatrick CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
891e5dd7070Spatrick for (unsigned I = 0; I != N; ++I, ++BI) {
892e5dd7070Spatrick assert(BI != CD->bases_end());
893e5dd7070Spatrick if (!First)
894e5dd7070Spatrick Out << ", ";
895a9ac8606Spatrick getStructBase(I).printPretty(Out, Policy, BI->getType(), Ctx);
896e5dd7070Spatrick First = false;
897e5dd7070Spatrick }
898e5dd7070Spatrick }
899e5dd7070Spatrick for (const auto *FI : RD->fields()) {
900e5dd7070Spatrick if (!First)
901e5dd7070Spatrick Out << ", ";
902e5dd7070Spatrick if (FI->isUnnamedBitfield()) continue;
903e5dd7070Spatrick getStructField(FI->getFieldIndex()).
904a9ac8606Spatrick printPretty(Out, Policy, FI->getType(), Ctx);
905e5dd7070Spatrick First = false;
906e5dd7070Spatrick }
907e5dd7070Spatrick Out << '}';
908e5dd7070Spatrick return;
909e5dd7070Spatrick }
910e5dd7070Spatrick case APValue::Union:
911e5dd7070Spatrick Out << '{';
912e5dd7070Spatrick if (const FieldDecl *FD = getUnionField()) {
913e5dd7070Spatrick Out << "." << *FD << " = ";
914a9ac8606Spatrick getUnionValue().printPretty(Out, Policy, FD->getType(), Ctx);
915e5dd7070Spatrick }
916e5dd7070Spatrick Out << '}';
917e5dd7070Spatrick return;
918e5dd7070Spatrick case APValue::MemberPointer:
919e5dd7070Spatrick // FIXME: This is not enough to unambiguously identify the member in a
920e5dd7070Spatrick // multiple-inheritance scenario.
921e5dd7070Spatrick if (const ValueDecl *VD = getMemberPointerDecl()) {
922e5dd7070Spatrick Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;
923e5dd7070Spatrick return;
924e5dd7070Spatrick }
925e5dd7070Spatrick Out << "0";
926e5dd7070Spatrick return;
927e5dd7070Spatrick case APValue::AddrLabelDiff:
928e5dd7070Spatrick Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName();
929e5dd7070Spatrick Out << " - ";
930e5dd7070Spatrick Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName();
931e5dd7070Spatrick return;
932e5dd7070Spatrick }
933e5dd7070Spatrick llvm_unreachable("Unknown APValue kind!");
934e5dd7070Spatrick }
935e5dd7070Spatrick
getAsString(const ASTContext & Ctx,QualType Ty) const936e5dd7070Spatrick std::string APValue::getAsString(const ASTContext &Ctx, QualType Ty) const {
937e5dd7070Spatrick std::string Result;
938e5dd7070Spatrick llvm::raw_string_ostream Out(Result);
939e5dd7070Spatrick printPretty(Out, Ctx, Ty);
940e5dd7070Spatrick Out.flush();
941e5dd7070Spatrick return Result;
942e5dd7070Spatrick }
943e5dd7070Spatrick
toIntegralConstant(APSInt & Result,QualType SrcTy,const ASTContext & Ctx) const944e5dd7070Spatrick bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy,
945e5dd7070Spatrick const ASTContext &Ctx) const {
946e5dd7070Spatrick if (isInt()) {
947e5dd7070Spatrick Result = getInt();
948e5dd7070Spatrick return true;
949e5dd7070Spatrick }
950e5dd7070Spatrick
951e5dd7070Spatrick if (isLValue() && isNullPointer()) {
952e5dd7070Spatrick Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy);
953e5dd7070Spatrick return true;
954e5dd7070Spatrick }
955e5dd7070Spatrick
956e5dd7070Spatrick if (isLValue() && !getLValueBase()) {
957e5dd7070Spatrick Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy);
958e5dd7070Spatrick return true;
959e5dd7070Spatrick }
960e5dd7070Spatrick
961e5dd7070Spatrick return false;
962e5dd7070Spatrick }
963e5dd7070Spatrick
getLValueBase() const964e5dd7070Spatrick const APValue::LValueBase APValue::getLValueBase() const {
965e5dd7070Spatrick assert(isLValue() && "Invalid accessor");
966a9ac8606Spatrick return ((const LV *)(const void *)&Data)->Base;
967e5dd7070Spatrick }
968e5dd7070Spatrick
isLValueOnePastTheEnd() const969e5dd7070Spatrick bool APValue::isLValueOnePastTheEnd() const {
970e5dd7070Spatrick assert(isLValue() && "Invalid accessor");
971a9ac8606Spatrick return ((const LV *)(const void *)&Data)->IsOnePastTheEnd;
972e5dd7070Spatrick }
973e5dd7070Spatrick
getLValueOffset()974e5dd7070Spatrick CharUnits &APValue::getLValueOffset() {
975e5dd7070Spatrick assert(isLValue() && "Invalid accessor");
976a9ac8606Spatrick return ((LV *)(void *)&Data)->Offset;
977e5dd7070Spatrick }
978e5dd7070Spatrick
hasLValuePath() const979e5dd7070Spatrick bool APValue::hasLValuePath() const {
980e5dd7070Spatrick assert(isLValue() && "Invalid accessor");
981a9ac8606Spatrick return ((const LV *)(const char *)&Data)->hasPath();
982e5dd7070Spatrick }
983e5dd7070Spatrick
getLValuePath() const984e5dd7070Spatrick ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
985e5dd7070Spatrick assert(isLValue() && hasLValuePath() && "Invalid accessor");
986a9ac8606Spatrick const LV &LVal = *((const LV *)(const char *)&Data);
987*12c85518Srobert return llvm::ArrayRef(LVal.getPath(), LVal.PathLength);
988e5dd7070Spatrick }
989e5dd7070Spatrick
getLValueCallIndex() const990e5dd7070Spatrick unsigned APValue::getLValueCallIndex() const {
991e5dd7070Spatrick assert(isLValue() && "Invalid accessor");
992a9ac8606Spatrick return ((const LV *)(const char *)&Data)->Base.getCallIndex();
993e5dd7070Spatrick }
994e5dd7070Spatrick
getLValueVersion() const995e5dd7070Spatrick unsigned APValue::getLValueVersion() const {
996e5dd7070Spatrick assert(isLValue() && "Invalid accessor");
997a9ac8606Spatrick return ((const LV *)(const char *)&Data)->Base.getVersion();
998e5dd7070Spatrick }
999e5dd7070Spatrick
isNullPointer() const1000e5dd7070Spatrick bool APValue::isNullPointer() const {
1001e5dd7070Spatrick assert(isLValue() && "Invalid usage");
1002a9ac8606Spatrick return ((const LV *)(const char *)&Data)->IsNullPtr;
1003e5dd7070Spatrick }
1004e5dd7070Spatrick
setLValue(LValueBase B,const CharUnits & O,NoLValuePath,bool IsNullPtr)1005e5dd7070Spatrick void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
1006e5dd7070Spatrick bool IsNullPtr) {
1007e5dd7070Spatrick assert(isLValue() && "Invalid accessor");
1008a9ac8606Spatrick LV &LVal = *((LV *)(char *)&Data);
1009e5dd7070Spatrick LVal.Base = B;
1010e5dd7070Spatrick LVal.IsOnePastTheEnd = false;
1011e5dd7070Spatrick LVal.Offset = O;
1012e5dd7070Spatrick LVal.resizePath((unsigned)-1);
1013e5dd7070Spatrick LVal.IsNullPtr = IsNullPtr;
1014e5dd7070Spatrick }
1015e5dd7070Spatrick
1016a9ac8606Spatrick MutableArrayRef<APValue::LValuePathEntry>
setLValueUninit(LValueBase B,const CharUnits & O,unsigned Size,bool IsOnePastTheEnd,bool IsNullPtr)1017a9ac8606Spatrick APValue::setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size,
1018a9ac8606Spatrick bool IsOnePastTheEnd, bool IsNullPtr) {
1019e5dd7070Spatrick assert(isLValue() && "Invalid accessor");
1020a9ac8606Spatrick LV &LVal = *((LV *)(char *)&Data);
1021e5dd7070Spatrick LVal.Base = B;
1022e5dd7070Spatrick LVal.IsOnePastTheEnd = IsOnePastTheEnd;
1023e5dd7070Spatrick LVal.Offset = O;
1024e5dd7070Spatrick LVal.IsNullPtr = IsNullPtr;
1025a9ac8606Spatrick LVal.resizePath(Size);
1026a9ac8606Spatrick return {LVal.getPath(), Size};
1027a9ac8606Spatrick }
1028a9ac8606Spatrick
setLValue(LValueBase B,const CharUnits & O,ArrayRef<LValuePathEntry> Path,bool IsOnePastTheEnd,bool IsNullPtr)1029a9ac8606Spatrick void APValue::setLValue(LValueBase B, const CharUnits &O,
1030a9ac8606Spatrick ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
1031a9ac8606Spatrick bool IsNullPtr) {
1032a9ac8606Spatrick MutableArrayRef<APValue::LValuePathEntry> InternalPath =
1033a9ac8606Spatrick setLValueUninit(B, O, Path.size(), IsOnePastTheEnd, IsNullPtr);
1034a9ac8606Spatrick if (Path.size()) {
1035a9ac8606Spatrick memcpy(InternalPath.data(), Path.data(),
1036a9ac8606Spatrick Path.size() * sizeof(LValuePathEntry));
1037a9ac8606Spatrick }
1038a9ac8606Spatrick }
1039a9ac8606Spatrick
setUnion(const FieldDecl * Field,const APValue & Value)1040a9ac8606Spatrick void APValue::setUnion(const FieldDecl *Field, const APValue &Value) {
1041a9ac8606Spatrick assert(isUnion() && "Invalid accessor");
1042a9ac8606Spatrick ((UnionData *)(char *)&Data)->Field =
1043a9ac8606Spatrick Field ? Field->getCanonicalDecl() : nullptr;
1044a9ac8606Spatrick *((UnionData *)(char *)&Data)->Value = Value;
1045e5dd7070Spatrick }
1046e5dd7070Spatrick
getMemberPointerDecl() const1047e5dd7070Spatrick const ValueDecl *APValue::getMemberPointerDecl() const {
1048e5dd7070Spatrick assert(isMemberPointer() && "Invalid accessor");
1049e5dd7070Spatrick const MemberPointerData &MPD =
1050a9ac8606Spatrick *((const MemberPointerData *)(const char *)&Data);
1051e5dd7070Spatrick return MPD.MemberAndIsDerivedMember.getPointer();
1052e5dd7070Spatrick }
1053e5dd7070Spatrick
isMemberPointerToDerivedMember() const1054e5dd7070Spatrick bool APValue::isMemberPointerToDerivedMember() const {
1055e5dd7070Spatrick assert(isMemberPointer() && "Invalid accessor");
1056e5dd7070Spatrick const MemberPointerData &MPD =
1057a9ac8606Spatrick *((const MemberPointerData *)(const char *)&Data);
1058e5dd7070Spatrick return MPD.MemberAndIsDerivedMember.getInt();
1059e5dd7070Spatrick }
1060e5dd7070Spatrick
getMemberPointerPath() const1061e5dd7070Spatrick ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {
1062e5dd7070Spatrick assert(isMemberPointer() && "Invalid accessor");
1063e5dd7070Spatrick const MemberPointerData &MPD =
1064a9ac8606Spatrick *((const MemberPointerData *)(const char *)&Data);
1065*12c85518Srobert return llvm::ArrayRef(MPD.getPath(), MPD.PathLength);
1066e5dd7070Spatrick }
1067e5dd7070Spatrick
MakeLValue()1068e5dd7070Spatrick void APValue::MakeLValue() {
1069e5dd7070Spatrick assert(isAbsent() && "Bad state change");
1070e5dd7070Spatrick static_assert(sizeof(LV) <= DataSize, "LV too big");
1071a9ac8606Spatrick new ((void *)(char *)&Data) LV();
1072e5dd7070Spatrick Kind = LValue;
1073e5dd7070Spatrick }
1074e5dd7070Spatrick
MakeArray(unsigned InitElts,unsigned Size)1075e5dd7070Spatrick void APValue::MakeArray(unsigned InitElts, unsigned Size) {
1076e5dd7070Spatrick assert(isAbsent() && "Bad state change");
1077a9ac8606Spatrick new ((void *)(char *)&Data) Arr(InitElts, Size);
1078e5dd7070Spatrick Kind = Array;
1079e5dd7070Spatrick }
1080e5dd7070Spatrick
1081a9ac8606Spatrick MutableArrayRef<APValue::LValuePathEntry>
1082a9ac8606Spatrick setLValueUninit(APValue::LValueBase B, const CharUnits &O, unsigned Size,
1083a9ac8606Spatrick bool OnePastTheEnd, bool IsNullPtr);
1084a9ac8606Spatrick
1085a9ac8606Spatrick MutableArrayRef<const CXXRecordDecl *>
setMemberPointerUninit(const ValueDecl * Member,bool IsDerivedMember,unsigned Size)1086a9ac8606Spatrick APValue::setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember,
1087a9ac8606Spatrick unsigned Size) {
1088a9ac8606Spatrick assert(isAbsent() && "Bad state change");
1089a9ac8606Spatrick MemberPointerData *MPD = new ((void *)(char *)&Data) MemberPointerData;
1090a9ac8606Spatrick Kind = MemberPointer;
1091a9ac8606Spatrick MPD->MemberAndIsDerivedMember.setPointer(
1092a9ac8606Spatrick Member ? cast<ValueDecl>(Member->getCanonicalDecl()) : nullptr);
1093a9ac8606Spatrick MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
1094a9ac8606Spatrick MPD->resizePath(Size);
1095a9ac8606Spatrick return {MPD->getPath(), MPD->PathLength};
1096a9ac8606Spatrick }
1097a9ac8606Spatrick
MakeMemberPointer(const ValueDecl * Member,bool IsDerivedMember,ArrayRef<const CXXRecordDecl * > Path)1098e5dd7070Spatrick void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
1099e5dd7070Spatrick ArrayRef<const CXXRecordDecl *> Path) {
1100a9ac8606Spatrick MutableArrayRef<const CXXRecordDecl *> InternalPath =
1101a9ac8606Spatrick setMemberPointerUninit(Member, IsDerivedMember, Path.size());
1102a9ac8606Spatrick for (unsigned I = 0; I != Path.size(); ++I)
1103a9ac8606Spatrick InternalPath[I] = Path[I]->getCanonicalDecl();
1104a9ac8606Spatrick }
1105a9ac8606Spatrick
getLVForValue(const APValue & V,LVComputationKind computation)1106a9ac8606Spatrick LinkageInfo LinkageComputer::getLVForValue(const APValue &V,
1107a9ac8606Spatrick LVComputationKind computation) {
1108a9ac8606Spatrick LinkageInfo LV = LinkageInfo::external();
1109a9ac8606Spatrick
1110a9ac8606Spatrick auto MergeLV = [&](LinkageInfo MergeLV) {
1111a9ac8606Spatrick LV.merge(MergeLV);
1112a9ac8606Spatrick return LV.getLinkage() == InternalLinkage;
1113a9ac8606Spatrick };
1114a9ac8606Spatrick auto Merge = [&](const APValue &V) {
1115a9ac8606Spatrick return MergeLV(getLVForValue(V, computation));
1116a9ac8606Spatrick };
1117a9ac8606Spatrick
1118a9ac8606Spatrick switch (V.getKind()) {
1119a9ac8606Spatrick case APValue::None:
1120a9ac8606Spatrick case APValue::Indeterminate:
1121a9ac8606Spatrick case APValue::Int:
1122a9ac8606Spatrick case APValue::Float:
1123a9ac8606Spatrick case APValue::FixedPoint:
1124a9ac8606Spatrick case APValue::ComplexInt:
1125a9ac8606Spatrick case APValue::ComplexFloat:
1126a9ac8606Spatrick case APValue::Vector:
1127a9ac8606Spatrick break;
1128a9ac8606Spatrick
1129a9ac8606Spatrick case APValue::AddrLabelDiff:
1130a9ac8606Spatrick // Even for an inline function, it's not reasonable to treat a difference
1131a9ac8606Spatrick // between the addresses of labels as an external value.
1132a9ac8606Spatrick return LinkageInfo::internal();
1133a9ac8606Spatrick
1134a9ac8606Spatrick case APValue::Struct: {
1135a9ac8606Spatrick for (unsigned I = 0, N = V.getStructNumBases(); I != N; ++I)
1136a9ac8606Spatrick if (Merge(V.getStructBase(I)))
1137a9ac8606Spatrick break;
1138a9ac8606Spatrick for (unsigned I = 0, N = V.getStructNumFields(); I != N; ++I)
1139a9ac8606Spatrick if (Merge(V.getStructField(I)))
1140a9ac8606Spatrick break;
1141a9ac8606Spatrick break;
1142a9ac8606Spatrick }
1143a9ac8606Spatrick
1144a9ac8606Spatrick case APValue::Union:
1145a9ac8606Spatrick if (V.getUnionField())
1146a9ac8606Spatrick Merge(V.getUnionValue());
1147a9ac8606Spatrick break;
1148a9ac8606Spatrick
1149a9ac8606Spatrick case APValue::Array: {
1150a9ac8606Spatrick for (unsigned I = 0, N = V.getArrayInitializedElts(); I != N; ++I)
1151a9ac8606Spatrick if (Merge(V.getArrayInitializedElt(I)))
1152a9ac8606Spatrick break;
1153a9ac8606Spatrick if (V.hasArrayFiller())
1154a9ac8606Spatrick Merge(V.getArrayFiller());
1155a9ac8606Spatrick break;
1156a9ac8606Spatrick }
1157a9ac8606Spatrick
1158a9ac8606Spatrick case APValue::LValue: {
1159a9ac8606Spatrick if (!V.getLValueBase()) {
1160a9ac8606Spatrick // Null or absolute address: this is external.
1161a9ac8606Spatrick } else if (const auto *VD =
1162a9ac8606Spatrick V.getLValueBase().dyn_cast<const ValueDecl *>()) {
1163a9ac8606Spatrick if (VD && MergeLV(getLVForDecl(VD, computation)))
1164a9ac8606Spatrick break;
1165a9ac8606Spatrick } else if (const auto TI = V.getLValueBase().dyn_cast<TypeInfoLValue>()) {
1166a9ac8606Spatrick if (MergeLV(getLVForType(*TI.getType(), computation)))
1167a9ac8606Spatrick break;
1168a9ac8606Spatrick } else if (const Expr *E = V.getLValueBase().dyn_cast<const Expr *>()) {
1169a9ac8606Spatrick // Almost all expression bases are internal. The exception is
1170a9ac8606Spatrick // lifetime-extended temporaries.
1171a9ac8606Spatrick // FIXME: These should be modeled as having the
1172a9ac8606Spatrick // LifetimeExtendedTemporaryDecl itself as the base.
1173a9ac8606Spatrick // FIXME: If we permit Objective-C object literals in template arguments,
1174a9ac8606Spatrick // they should not imply internal linkage.
1175a9ac8606Spatrick auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E);
1176a9ac8606Spatrick if (!MTE || MTE->getStorageDuration() == SD_FullExpression)
1177a9ac8606Spatrick return LinkageInfo::internal();
1178a9ac8606Spatrick if (MergeLV(getLVForDecl(MTE->getExtendingDecl(), computation)))
1179a9ac8606Spatrick break;
1180a9ac8606Spatrick } else {
1181a9ac8606Spatrick assert(V.getLValueBase().is<DynamicAllocLValue>() &&
1182a9ac8606Spatrick "unexpected LValueBase kind");
1183a9ac8606Spatrick return LinkageInfo::internal();
1184a9ac8606Spatrick }
1185a9ac8606Spatrick // The lvalue path doesn't matter: pointers to all subobjects always have
1186a9ac8606Spatrick // the same visibility as pointers to the complete object.
1187a9ac8606Spatrick break;
1188a9ac8606Spatrick }
1189a9ac8606Spatrick
1190a9ac8606Spatrick case APValue::MemberPointer:
1191a9ac8606Spatrick if (const NamedDecl *D = V.getMemberPointerDecl())
1192a9ac8606Spatrick MergeLV(getLVForDecl(D, computation));
1193a9ac8606Spatrick // Note that we could have a base-to-derived conversion here to a member of
1194a9ac8606Spatrick // a derived class with less linkage/visibility. That's covered by the
1195a9ac8606Spatrick // linkage and visibility of the value's type.
1196a9ac8606Spatrick break;
1197a9ac8606Spatrick }
1198a9ac8606Spatrick
1199a9ac8606Spatrick return LV;
1200e5dd7070Spatrick }
1201