xref: /openbsd-src/gnu/llvm/clang/lib/AST/APValue.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
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