1f4a2713aSLionel Sambuc //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file implements the APValue class.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc #include "clang/AST/APValue.h"
15f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
16f4a2713aSLionel Sambuc #include "clang/AST/CharUnits.h"
17f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h"
18f4a2713aSLionel Sambuc #include "clang/AST/Expr.h"
19f4a2713aSLionel Sambuc #include "clang/AST/Type.h"
20f4a2713aSLionel Sambuc #include "clang/Basic/Diagnostic.h"
21f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
22f4a2713aSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
23f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
24f4a2713aSLionel Sambuc using namespace clang;
25f4a2713aSLionel Sambuc
26f4a2713aSLionel Sambuc namespace {
27f4a2713aSLionel Sambuc struct LVBase {
28f4a2713aSLionel Sambuc llvm::PointerIntPair<APValue::LValueBase, 1, bool> BaseAndIsOnePastTheEnd;
29f4a2713aSLionel Sambuc CharUnits Offset;
30f4a2713aSLionel Sambuc unsigned PathLength;
31f4a2713aSLionel Sambuc unsigned CallIndex;
32f4a2713aSLionel Sambuc };
33f4a2713aSLionel Sambuc }
34f4a2713aSLionel Sambuc
35f4a2713aSLionel Sambuc struct APValue::LV : LVBase {
36f4a2713aSLionel Sambuc static const unsigned InlinePathSpace =
37*0a6a1f1dSLionel Sambuc (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
38f4a2713aSLionel Sambuc
39f4a2713aSLionel Sambuc /// Path - The sequence of base classes, fields and array indices to follow to
40f4a2713aSLionel Sambuc /// walk from Base to the subobject. When performing GCC-style folding, there
41f4a2713aSLionel Sambuc /// may not be such a path.
42f4a2713aSLionel Sambuc union {
43f4a2713aSLionel Sambuc LValuePathEntry Path[InlinePathSpace];
44f4a2713aSLionel Sambuc LValuePathEntry *PathPtr;
45f4a2713aSLionel Sambuc };
46f4a2713aSLionel Sambuc
LVAPValue::LV47f4a2713aSLionel Sambuc LV() { PathLength = (unsigned)-1; }
~LVAPValue::LV48f4a2713aSLionel Sambuc ~LV() { resizePath(0); }
49f4a2713aSLionel Sambuc
resizePathAPValue::LV50f4a2713aSLionel Sambuc void resizePath(unsigned Length) {
51f4a2713aSLionel Sambuc if (Length == PathLength)
52f4a2713aSLionel Sambuc return;
53f4a2713aSLionel Sambuc if (hasPathPtr())
54f4a2713aSLionel Sambuc delete [] PathPtr;
55f4a2713aSLionel Sambuc PathLength = Length;
56f4a2713aSLionel Sambuc if (hasPathPtr())
57f4a2713aSLionel Sambuc PathPtr = new LValuePathEntry[Length];
58f4a2713aSLionel Sambuc }
59f4a2713aSLionel Sambuc
hasPathAPValue::LV60f4a2713aSLionel Sambuc bool hasPath() const { return PathLength != (unsigned)-1; }
hasPathPtrAPValue::LV61f4a2713aSLionel Sambuc bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }
62f4a2713aSLionel Sambuc
getPathAPValue::LV63f4a2713aSLionel Sambuc LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }
getPathAPValue::LV64f4a2713aSLionel Sambuc const LValuePathEntry *getPath() const {
65f4a2713aSLionel Sambuc return hasPathPtr() ? PathPtr : Path;
66f4a2713aSLionel Sambuc }
67f4a2713aSLionel Sambuc };
68f4a2713aSLionel Sambuc
69f4a2713aSLionel Sambuc namespace {
70f4a2713aSLionel Sambuc struct MemberPointerBase {
71f4a2713aSLionel Sambuc llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember;
72f4a2713aSLionel Sambuc unsigned PathLength;
73f4a2713aSLionel Sambuc };
74f4a2713aSLionel Sambuc }
75f4a2713aSLionel Sambuc
76f4a2713aSLionel Sambuc struct APValue::MemberPointerData : MemberPointerBase {
77f4a2713aSLionel Sambuc static const unsigned InlinePathSpace =
78*0a6a1f1dSLionel Sambuc (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*);
79f4a2713aSLionel Sambuc typedef const CXXRecordDecl *PathElem;
80f4a2713aSLionel Sambuc union {
81f4a2713aSLionel Sambuc PathElem Path[InlinePathSpace];
82f4a2713aSLionel Sambuc PathElem *PathPtr;
83f4a2713aSLionel Sambuc };
84f4a2713aSLionel Sambuc
MemberPointerDataAPValue::MemberPointerData85f4a2713aSLionel Sambuc MemberPointerData() { PathLength = 0; }
~MemberPointerDataAPValue::MemberPointerData86f4a2713aSLionel Sambuc ~MemberPointerData() { resizePath(0); }
87f4a2713aSLionel Sambuc
resizePathAPValue::MemberPointerData88f4a2713aSLionel Sambuc void resizePath(unsigned Length) {
89f4a2713aSLionel Sambuc if (Length == PathLength)
90f4a2713aSLionel Sambuc return;
91f4a2713aSLionel Sambuc if (hasPathPtr())
92f4a2713aSLionel Sambuc delete [] PathPtr;
93f4a2713aSLionel Sambuc PathLength = Length;
94f4a2713aSLionel Sambuc if (hasPathPtr())
95f4a2713aSLionel Sambuc PathPtr = new PathElem[Length];
96f4a2713aSLionel Sambuc }
97f4a2713aSLionel Sambuc
hasPathPtrAPValue::MemberPointerData98f4a2713aSLionel Sambuc bool hasPathPtr() const { return PathLength > InlinePathSpace; }
99f4a2713aSLionel Sambuc
getPathAPValue::MemberPointerData100f4a2713aSLionel Sambuc PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; }
getPathAPValue::MemberPointerData101f4a2713aSLionel Sambuc const PathElem *getPath() const {
102f4a2713aSLionel Sambuc return hasPathPtr() ? PathPtr : Path;
103f4a2713aSLionel Sambuc }
104f4a2713aSLionel Sambuc };
105f4a2713aSLionel Sambuc
106f4a2713aSLionel Sambuc // FIXME: Reduce the malloc traffic here.
107f4a2713aSLionel Sambuc
Arr(unsigned NumElts,unsigned Size)108f4a2713aSLionel Sambuc APValue::Arr::Arr(unsigned NumElts, unsigned Size) :
109f4a2713aSLionel Sambuc Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]),
110f4a2713aSLionel Sambuc NumElts(NumElts), ArrSize(Size) {}
~Arr()111f4a2713aSLionel Sambuc APValue::Arr::~Arr() { delete [] Elts; }
112f4a2713aSLionel Sambuc
StructData(unsigned NumBases,unsigned NumFields)113f4a2713aSLionel Sambuc APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) :
114f4a2713aSLionel Sambuc Elts(new APValue[NumBases+NumFields]),
115f4a2713aSLionel Sambuc NumBases(NumBases), NumFields(NumFields) {}
~StructData()116f4a2713aSLionel Sambuc APValue::StructData::~StructData() {
117f4a2713aSLionel Sambuc delete [] Elts;
118f4a2713aSLionel Sambuc }
119f4a2713aSLionel Sambuc
UnionData()120*0a6a1f1dSLionel Sambuc APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {}
~UnionData()121f4a2713aSLionel Sambuc APValue::UnionData::~UnionData () {
122f4a2713aSLionel Sambuc delete Value;
123f4a2713aSLionel Sambuc }
124f4a2713aSLionel Sambuc
APValue(const APValue & RHS)125f4a2713aSLionel Sambuc APValue::APValue(const APValue &RHS) : Kind(Uninitialized) {
126f4a2713aSLionel Sambuc switch (RHS.getKind()) {
127f4a2713aSLionel Sambuc case Uninitialized:
128f4a2713aSLionel Sambuc break;
129f4a2713aSLionel Sambuc case Int:
130f4a2713aSLionel Sambuc MakeInt();
131f4a2713aSLionel Sambuc setInt(RHS.getInt());
132f4a2713aSLionel Sambuc break;
133f4a2713aSLionel Sambuc case Float:
134f4a2713aSLionel Sambuc MakeFloat();
135f4a2713aSLionel Sambuc setFloat(RHS.getFloat());
136f4a2713aSLionel Sambuc break;
137f4a2713aSLionel Sambuc case Vector:
138f4a2713aSLionel Sambuc MakeVector();
139*0a6a1f1dSLionel Sambuc setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts,
140f4a2713aSLionel Sambuc RHS.getVectorLength());
141f4a2713aSLionel Sambuc break;
142f4a2713aSLionel Sambuc case ComplexInt:
143f4a2713aSLionel Sambuc MakeComplexInt();
144f4a2713aSLionel Sambuc setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
145f4a2713aSLionel Sambuc break;
146f4a2713aSLionel Sambuc case ComplexFloat:
147f4a2713aSLionel Sambuc MakeComplexFloat();
148f4a2713aSLionel Sambuc setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
149f4a2713aSLionel Sambuc break;
150f4a2713aSLionel Sambuc case LValue:
151f4a2713aSLionel Sambuc MakeLValue();
152f4a2713aSLionel Sambuc if (RHS.hasLValuePath())
153f4a2713aSLionel Sambuc setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
154f4a2713aSLionel Sambuc RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex());
155f4a2713aSLionel Sambuc else
156f4a2713aSLionel Sambuc setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
157f4a2713aSLionel Sambuc RHS.getLValueCallIndex());
158f4a2713aSLionel Sambuc break;
159f4a2713aSLionel Sambuc case Array:
160f4a2713aSLionel Sambuc MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
161f4a2713aSLionel Sambuc for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)
162f4a2713aSLionel Sambuc getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);
163f4a2713aSLionel Sambuc if (RHS.hasArrayFiller())
164f4a2713aSLionel Sambuc getArrayFiller() = RHS.getArrayFiller();
165f4a2713aSLionel Sambuc break;
166f4a2713aSLionel Sambuc case Struct:
167f4a2713aSLionel Sambuc MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());
168f4a2713aSLionel Sambuc for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I)
169f4a2713aSLionel Sambuc getStructBase(I) = RHS.getStructBase(I);
170f4a2713aSLionel Sambuc for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I)
171f4a2713aSLionel Sambuc getStructField(I) = RHS.getStructField(I);
172f4a2713aSLionel Sambuc break;
173f4a2713aSLionel Sambuc case Union:
174f4a2713aSLionel Sambuc MakeUnion();
175f4a2713aSLionel Sambuc setUnion(RHS.getUnionField(), RHS.getUnionValue());
176f4a2713aSLionel Sambuc break;
177f4a2713aSLionel Sambuc case MemberPointer:
178f4a2713aSLionel Sambuc MakeMemberPointer(RHS.getMemberPointerDecl(),
179f4a2713aSLionel Sambuc RHS.isMemberPointerToDerivedMember(),
180f4a2713aSLionel Sambuc RHS.getMemberPointerPath());
181f4a2713aSLionel Sambuc break;
182f4a2713aSLionel Sambuc case AddrLabelDiff:
183f4a2713aSLionel Sambuc MakeAddrLabelDiff();
184f4a2713aSLionel Sambuc setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS());
185f4a2713aSLionel Sambuc break;
186f4a2713aSLionel Sambuc }
187f4a2713aSLionel Sambuc }
188f4a2713aSLionel Sambuc
DestroyDataAndMakeUninit()189f4a2713aSLionel Sambuc void APValue::DestroyDataAndMakeUninit() {
190f4a2713aSLionel Sambuc if (Kind == Int)
191*0a6a1f1dSLionel Sambuc ((APSInt*)(char*)Data.buffer)->~APSInt();
192f4a2713aSLionel Sambuc else if (Kind == Float)
193*0a6a1f1dSLionel Sambuc ((APFloat*)(char*)Data.buffer)->~APFloat();
194f4a2713aSLionel Sambuc else if (Kind == Vector)
195*0a6a1f1dSLionel Sambuc ((Vec*)(char*)Data.buffer)->~Vec();
196f4a2713aSLionel Sambuc else if (Kind == ComplexInt)
197*0a6a1f1dSLionel Sambuc ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt();
198f4a2713aSLionel Sambuc else if (Kind == ComplexFloat)
199*0a6a1f1dSLionel Sambuc ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat();
200f4a2713aSLionel Sambuc else if (Kind == LValue)
201*0a6a1f1dSLionel Sambuc ((LV*)(char*)Data.buffer)->~LV();
202f4a2713aSLionel Sambuc else if (Kind == Array)
203*0a6a1f1dSLionel Sambuc ((Arr*)(char*)Data.buffer)->~Arr();
204f4a2713aSLionel Sambuc else if (Kind == Struct)
205*0a6a1f1dSLionel Sambuc ((StructData*)(char*)Data.buffer)->~StructData();
206f4a2713aSLionel Sambuc else if (Kind == Union)
207*0a6a1f1dSLionel Sambuc ((UnionData*)(char*)Data.buffer)->~UnionData();
208f4a2713aSLionel Sambuc else if (Kind == MemberPointer)
209*0a6a1f1dSLionel Sambuc ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData();
210f4a2713aSLionel Sambuc else if (Kind == AddrLabelDiff)
211*0a6a1f1dSLionel Sambuc ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData();
212f4a2713aSLionel Sambuc Kind = Uninitialized;
213f4a2713aSLionel Sambuc }
214f4a2713aSLionel Sambuc
needsCleanup() const215f4a2713aSLionel Sambuc bool APValue::needsCleanup() const {
216f4a2713aSLionel Sambuc switch (getKind()) {
217f4a2713aSLionel Sambuc case Uninitialized:
218f4a2713aSLionel Sambuc case AddrLabelDiff:
219f4a2713aSLionel Sambuc return false;
220f4a2713aSLionel Sambuc case Struct:
221f4a2713aSLionel Sambuc case Union:
222f4a2713aSLionel Sambuc case Array:
223f4a2713aSLionel Sambuc case Vector:
224f4a2713aSLionel Sambuc return true;
225f4a2713aSLionel Sambuc case Int:
226f4a2713aSLionel Sambuc return getInt().needsCleanup();
227f4a2713aSLionel Sambuc case Float:
228f4a2713aSLionel Sambuc return getFloat().needsCleanup();
229f4a2713aSLionel Sambuc case ComplexFloat:
230f4a2713aSLionel Sambuc assert(getComplexFloatImag().needsCleanup() ==
231f4a2713aSLionel Sambuc getComplexFloatReal().needsCleanup() &&
232f4a2713aSLionel Sambuc "In _Complex float types, real and imaginary values always have the "
233f4a2713aSLionel Sambuc "same size.");
234f4a2713aSLionel Sambuc return getComplexFloatReal().needsCleanup();
235f4a2713aSLionel Sambuc case ComplexInt:
236f4a2713aSLionel Sambuc assert(getComplexIntImag().needsCleanup() ==
237f4a2713aSLionel Sambuc getComplexIntReal().needsCleanup() &&
238f4a2713aSLionel Sambuc "In _Complex int types, real and imaginary values must have the "
239f4a2713aSLionel Sambuc "same size.");
240f4a2713aSLionel Sambuc return getComplexIntReal().needsCleanup();
241f4a2713aSLionel Sambuc case LValue:
242*0a6a1f1dSLionel Sambuc return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr();
243f4a2713aSLionel Sambuc case MemberPointer:
244*0a6a1f1dSLionel Sambuc return reinterpret_cast<const MemberPointerData *>(Data.buffer)
245*0a6a1f1dSLionel Sambuc ->hasPathPtr();
246f4a2713aSLionel Sambuc }
247f4a2713aSLionel Sambuc llvm_unreachable("Unknown APValue kind!");
248f4a2713aSLionel Sambuc }
249f4a2713aSLionel Sambuc
swap(APValue & RHS)250f4a2713aSLionel Sambuc void APValue::swap(APValue &RHS) {
251f4a2713aSLionel Sambuc std::swap(Kind, RHS.Kind);
252*0a6a1f1dSLionel Sambuc char TmpData[DataSize];
253*0a6a1f1dSLionel Sambuc memcpy(TmpData, Data.buffer, DataSize);
254*0a6a1f1dSLionel Sambuc memcpy(Data.buffer, RHS.Data.buffer, DataSize);
255*0a6a1f1dSLionel Sambuc memcpy(RHS.Data.buffer, TmpData, DataSize);
256f4a2713aSLionel Sambuc }
257f4a2713aSLionel Sambuc
dump() const258f4a2713aSLionel Sambuc void APValue::dump() const {
259f4a2713aSLionel Sambuc dump(llvm::errs());
260f4a2713aSLionel Sambuc llvm::errs() << '\n';
261f4a2713aSLionel Sambuc }
262f4a2713aSLionel Sambuc
GetApproxValue(const llvm::APFloat & F)263f4a2713aSLionel Sambuc static double GetApproxValue(const llvm::APFloat &F) {
264f4a2713aSLionel Sambuc llvm::APFloat V = F;
265f4a2713aSLionel Sambuc bool ignored;
266f4a2713aSLionel Sambuc V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
267f4a2713aSLionel Sambuc &ignored);
268f4a2713aSLionel Sambuc return V.convertToDouble();
269f4a2713aSLionel Sambuc }
270f4a2713aSLionel Sambuc
dump(raw_ostream & OS) const271f4a2713aSLionel Sambuc void APValue::dump(raw_ostream &OS) const {
272f4a2713aSLionel Sambuc switch (getKind()) {
273f4a2713aSLionel Sambuc case Uninitialized:
274f4a2713aSLionel Sambuc OS << "Uninitialized";
275f4a2713aSLionel Sambuc return;
276f4a2713aSLionel Sambuc case Int:
277f4a2713aSLionel Sambuc OS << "Int: " << getInt();
278f4a2713aSLionel Sambuc return;
279f4a2713aSLionel Sambuc case Float:
280f4a2713aSLionel Sambuc OS << "Float: " << GetApproxValue(getFloat());
281f4a2713aSLionel Sambuc return;
282f4a2713aSLionel Sambuc case Vector:
283f4a2713aSLionel Sambuc OS << "Vector: ";
284f4a2713aSLionel Sambuc getVectorElt(0).dump(OS);
285f4a2713aSLionel Sambuc for (unsigned i = 1; i != getVectorLength(); ++i) {
286f4a2713aSLionel Sambuc OS << ", ";
287f4a2713aSLionel Sambuc getVectorElt(i).dump(OS);
288f4a2713aSLionel Sambuc }
289f4a2713aSLionel Sambuc return;
290f4a2713aSLionel Sambuc case ComplexInt:
291f4a2713aSLionel Sambuc OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
292f4a2713aSLionel Sambuc return;
293f4a2713aSLionel Sambuc case ComplexFloat:
294f4a2713aSLionel Sambuc OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
295f4a2713aSLionel Sambuc << ", " << GetApproxValue(getComplexFloatImag());
296f4a2713aSLionel Sambuc return;
297f4a2713aSLionel Sambuc case LValue:
298f4a2713aSLionel Sambuc OS << "LValue: <todo>";
299f4a2713aSLionel Sambuc return;
300f4a2713aSLionel Sambuc case Array:
301f4a2713aSLionel Sambuc OS << "Array: ";
302f4a2713aSLionel Sambuc for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
303f4a2713aSLionel Sambuc getArrayInitializedElt(I).dump(OS);
304f4a2713aSLionel Sambuc if (I != getArraySize() - 1) OS << ", ";
305f4a2713aSLionel Sambuc }
306f4a2713aSLionel Sambuc if (hasArrayFiller()) {
307f4a2713aSLionel Sambuc OS << getArraySize() - getArrayInitializedElts() << " x ";
308f4a2713aSLionel Sambuc getArrayFiller().dump(OS);
309f4a2713aSLionel Sambuc }
310f4a2713aSLionel Sambuc return;
311f4a2713aSLionel Sambuc case Struct:
312f4a2713aSLionel Sambuc OS << "Struct ";
313f4a2713aSLionel Sambuc if (unsigned N = getStructNumBases()) {
314f4a2713aSLionel Sambuc OS << " bases: ";
315f4a2713aSLionel Sambuc getStructBase(0).dump(OS);
316f4a2713aSLionel Sambuc for (unsigned I = 1; I != N; ++I) {
317f4a2713aSLionel Sambuc OS << ", ";
318f4a2713aSLionel Sambuc getStructBase(I).dump(OS);
319f4a2713aSLionel Sambuc }
320f4a2713aSLionel Sambuc }
321f4a2713aSLionel Sambuc if (unsigned N = getStructNumFields()) {
322f4a2713aSLionel Sambuc OS << " fields: ";
323f4a2713aSLionel Sambuc getStructField(0).dump(OS);
324f4a2713aSLionel Sambuc for (unsigned I = 1; I != N; ++I) {
325f4a2713aSLionel Sambuc OS << ", ";
326f4a2713aSLionel Sambuc getStructField(I).dump(OS);
327f4a2713aSLionel Sambuc }
328f4a2713aSLionel Sambuc }
329f4a2713aSLionel Sambuc return;
330f4a2713aSLionel Sambuc case Union:
331f4a2713aSLionel Sambuc OS << "Union: ";
332f4a2713aSLionel Sambuc getUnionValue().dump(OS);
333f4a2713aSLionel Sambuc return;
334f4a2713aSLionel Sambuc case MemberPointer:
335f4a2713aSLionel Sambuc OS << "MemberPointer: <todo>";
336f4a2713aSLionel Sambuc return;
337f4a2713aSLionel Sambuc case AddrLabelDiff:
338f4a2713aSLionel Sambuc OS << "AddrLabelDiff: <todo>";
339f4a2713aSLionel Sambuc return;
340f4a2713aSLionel Sambuc }
341f4a2713aSLionel Sambuc llvm_unreachable("Unknown APValue kind!");
342f4a2713aSLionel Sambuc }
343f4a2713aSLionel Sambuc
printPretty(raw_ostream & Out,ASTContext & Ctx,QualType Ty) const344f4a2713aSLionel Sambuc void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{
345f4a2713aSLionel Sambuc switch (getKind()) {
346f4a2713aSLionel Sambuc case APValue::Uninitialized:
347f4a2713aSLionel Sambuc Out << "<uninitialized>";
348f4a2713aSLionel Sambuc return;
349f4a2713aSLionel Sambuc case APValue::Int:
350f4a2713aSLionel Sambuc if (Ty->isBooleanType())
351f4a2713aSLionel Sambuc Out << (getInt().getBoolValue() ? "true" : "false");
352f4a2713aSLionel Sambuc else
353f4a2713aSLionel Sambuc Out << getInt();
354f4a2713aSLionel Sambuc return;
355f4a2713aSLionel Sambuc case APValue::Float:
356f4a2713aSLionel Sambuc Out << GetApproxValue(getFloat());
357f4a2713aSLionel Sambuc return;
358f4a2713aSLionel Sambuc case APValue::Vector: {
359f4a2713aSLionel Sambuc Out << '{';
360f4a2713aSLionel Sambuc QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
361f4a2713aSLionel Sambuc getVectorElt(0).printPretty(Out, Ctx, ElemTy);
362f4a2713aSLionel Sambuc for (unsigned i = 1; i != getVectorLength(); ++i) {
363f4a2713aSLionel Sambuc Out << ", ";
364f4a2713aSLionel Sambuc getVectorElt(i).printPretty(Out, Ctx, ElemTy);
365f4a2713aSLionel Sambuc }
366f4a2713aSLionel Sambuc Out << '}';
367f4a2713aSLionel Sambuc return;
368f4a2713aSLionel Sambuc }
369f4a2713aSLionel Sambuc case APValue::ComplexInt:
370f4a2713aSLionel Sambuc Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";
371f4a2713aSLionel Sambuc return;
372f4a2713aSLionel Sambuc case APValue::ComplexFloat:
373f4a2713aSLionel Sambuc Out << GetApproxValue(getComplexFloatReal()) << "+"
374f4a2713aSLionel Sambuc << GetApproxValue(getComplexFloatImag()) << "i";
375f4a2713aSLionel Sambuc return;
376f4a2713aSLionel Sambuc case APValue::LValue: {
377f4a2713aSLionel Sambuc LValueBase Base = getLValueBase();
378f4a2713aSLionel Sambuc if (!Base) {
379f4a2713aSLionel Sambuc Out << "0";
380f4a2713aSLionel Sambuc return;
381f4a2713aSLionel Sambuc }
382f4a2713aSLionel Sambuc
383f4a2713aSLionel Sambuc bool IsReference = Ty->isReferenceType();
384f4a2713aSLionel Sambuc QualType InnerTy
385f4a2713aSLionel Sambuc = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();
386f4a2713aSLionel Sambuc if (InnerTy.isNull())
387f4a2713aSLionel Sambuc InnerTy = Ty;
388f4a2713aSLionel Sambuc
389f4a2713aSLionel Sambuc if (!hasLValuePath()) {
390f4a2713aSLionel Sambuc // No lvalue path: just print the offset.
391f4a2713aSLionel Sambuc CharUnits O = getLValueOffset();
392f4a2713aSLionel Sambuc CharUnits S = Ctx.getTypeSizeInChars(InnerTy);
393f4a2713aSLionel Sambuc if (!O.isZero()) {
394f4a2713aSLionel Sambuc if (IsReference)
395f4a2713aSLionel Sambuc Out << "*(";
396f4a2713aSLionel Sambuc if (O % S) {
397f4a2713aSLionel Sambuc Out << "(char*)";
398f4a2713aSLionel Sambuc S = CharUnits::One();
399f4a2713aSLionel Sambuc }
400f4a2713aSLionel Sambuc Out << '&';
401f4a2713aSLionel Sambuc } else if (!IsReference)
402f4a2713aSLionel Sambuc Out << '&';
403f4a2713aSLionel Sambuc
404f4a2713aSLionel Sambuc if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
405f4a2713aSLionel Sambuc Out << *VD;
406*0a6a1f1dSLionel Sambuc else {
407*0a6a1f1dSLionel Sambuc assert(Base.get<const Expr *>() != nullptr &&
408*0a6a1f1dSLionel Sambuc "Expecting non-null Expr");
409*0a6a1f1dSLionel Sambuc Base.get<const Expr*>()->printPretty(Out, nullptr,
410*0a6a1f1dSLionel Sambuc Ctx.getPrintingPolicy());
411*0a6a1f1dSLionel Sambuc }
412*0a6a1f1dSLionel Sambuc
413f4a2713aSLionel Sambuc if (!O.isZero()) {
414f4a2713aSLionel Sambuc Out << " + " << (O / S);
415f4a2713aSLionel Sambuc if (IsReference)
416f4a2713aSLionel Sambuc Out << ')';
417f4a2713aSLionel Sambuc }
418f4a2713aSLionel Sambuc return;
419f4a2713aSLionel Sambuc }
420f4a2713aSLionel Sambuc
421f4a2713aSLionel Sambuc // We have an lvalue path. Print it out nicely.
422f4a2713aSLionel Sambuc if (!IsReference)
423f4a2713aSLionel Sambuc Out << '&';
424f4a2713aSLionel Sambuc else if (isLValueOnePastTheEnd())
425f4a2713aSLionel Sambuc Out << "*(&";
426f4a2713aSLionel Sambuc
427f4a2713aSLionel Sambuc QualType ElemTy;
428f4a2713aSLionel Sambuc if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
429f4a2713aSLionel Sambuc Out << *VD;
430f4a2713aSLionel Sambuc ElemTy = VD->getType();
431f4a2713aSLionel Sambuc } else {
432f4a2713aSLionel Sambuc const Expr *E = Base.get<const Expr*>();
433*0a6a1f1dSLionel Sambuc assert(E != nullptr && "Expecting non-null Expr");
434*0a6a1f1dSLionel Sambuc E->printPretty(Out, nullptr, Ctx.getPrintingPolicy());
435f4a2713aSLionel Sambuc ElemTy = E->getType();
436f4a2713aSLionel Sambuc }
437f4a2713aSLionel Sambuc
438f4a2713aSLionel Sambuc ArrayRef<LValuePathEntry> Path = getLValuePath();
439*0a6a1f1dSLionel Sambuc const CXXRecordDecl *CastToBase = nullptr;
440f4a2713aSLionel Sambuc for (unsigned I = 0, N = Path.size(); I != N; ++I) {
441f4a2713aSLionel Sambuc if (ElemTy->getAs<RecordType>()) {
442f4a2713aSLionel Sambuc // The lvalue refers to a class type, so the next path entry is a base
443f4a2713aSLionel Sambuc // or member.
444f4a2713aSLionel Sambuc const Decl *BaseOrMember =
445f4a2713aSLionel Sambuc BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer();
446f4a2713aSLionel Sambuc if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
447f4a2713aSLionel Sambuc CastToBase = RD;
448f4a2713aSLionel Sambuc ElemTy = Ctx.getRecordType(RD);
449f4a2713aSLionel Sambuc } else {
450f4a2713aSLionel Sambuc const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
451f4a2713aSLionel Sambuc Out << ".";
452f4a2713aSLionel Sambuc if (CastToBase)
453f4a2713aSLionel Sambuc Out << *CastToBase << "::";
454f4a2713aSLionel Sambuc Out << *VD;
455f4a2713aSLionel Sambuc ElemTy = VD->getType();
456f4a2713aSLionel Sambuc }
457f4a2713aSLionel Sambuc } else {
458f4a2713aSLionel Sambuc // The lvalue must refer to an array.
459f4a2713aSLionel Sambuc Out << '[' << Path[I].ArrayIndex << ']';
460f4a2713aSLionel Sambuc ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType();
461f4a2713aSLionel Sambuc }
462f4a2713aSLionel Sambuc }
463f4a2713aSLionel Sambuc
464f4a2713aSLionel Sambuc // Handle formatting of one-past-the-end lvalues.
465f4a2713aSLionel Sambuc if (isLValueOnePastTheEnd()) {
466f4a2713aSLionel Sambuc // FIXME: If CastToBase is non-0, we should prefix the output with
467f4a2713aSLionel Sambuc // "(CastToBase*)".
468f4a2713aSLionel Sambuc Out << " + 1";
469f4a2713aSLionel Sambuc if (IsReference)
470f4a2713aSLionel Sambuc Out << ')';
471f4a2713aSLionel Sambuc }
472f4a2713aSLionel Sambuc return;
473f4a2713aSLionel Sambuc }
474f4a2713aSLionel Sambuc case APValue::Array: {
475f4a2713aSLionel Sambuc const ArrayType *AT = Ctx.getAsArrayType(Ty);
476f4a2713aSLionel Sambuc QualType ElemTy = AT->getElementType();
477f4a2713aSLionel Sambuc Out << '{';
478f4a2713aSLionel Sambuc if (unsigned N = getArrayInitializedElts()) {
479f4a2713aSLionel Sambuc getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy);
480f4a2713aSLionel Sambuc for (unsigned I = 1; I != N; ++I) {
481f4a2713aSLionel Sambuc Out << ", ";
482f4a2713aSLionel Sambuc if (I == 10) {
483f4a2713aSLionel Sambuc // Avoid printing out the entire contents of large arrays.
484f4a2713aSLionel Sambuc Out << "...";
485f4a2713aSLionel Sambuc break;
486f4a2713aSLionel Sambuc }
487f4a2713aSLionel Sambuc getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy);
488f4a2713aSLionel Sambuc }
489f4a2713aSLionel Sambuc }
490f4a2713aSLionel Sambuc Out << '}';
491f4a2713aSLionel Sambuc return;
492f4a2713aSLionel Sambuc }
493f4a2713aSLionel Sambuc case APValue::Struct: {
494f4a2713aSLionel Sambuc Out << '{';
495f4a2713aSLionel Sambuc const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
496f4a2713aSLionel Sambuc bool First = true;
497f4a2713aSLionel Sambuc if (unsigned N = getStructNumBases()) {
498f4a2713aSLionel Sambuc const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
499f4a2713aSLionel Sambuc CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
500f4a2713aSLionel Sambuc for (unsigned I = 0; I != N; ++I, ++BI) {
501f4a2713aSLionel Sambuc assert(BI != CD->bases_end());
502f4a2713aSLionel Sambuc if (!First)
503f4a2713aSLionel Sambuc Out << ", ";
504f4a2713aSLionel Sambuc getStructBase(I).printPretty(Out, Ctx, BI->getType());
505f4a2713aSLionel Sambuc First = false;
506f4a2713aSLionel Sambuc }
507f4a2713aSLionel Sambuc }
508*0a6a1f1dSLionel Sambuc for (const auto *FI : RD->fields()) {
509f4a2713aSLionel Sambuc if (!First)
510f4a2713aSLionel Sambuc Out << ", ";
511f4a2713aSLionel Sambuc if (FI->isUnnamedBitfield()) continue;
512f4a2713aSLionel Sambuc getStructField(FI->getFieldIndex()).
513f4a2713aSLionel Sambuc printPretty(Out, Ctx, FI->getType());
514f4a2713aSLionel Sambuc First = false;
515f4a2713aSLionel Sambuc }
516f4a2713aSLionel Sambuc Out << '}';
517f4a2713aSLionel Sambuc return;
518f4a2713aSLionel Sambuc }
519f4a2713aSLionel Sambuc case APValue::Union:
520f4a2713aSLionel Sambuc Out << '{';
521f4a2713aSLionel Sambuc if (const FieldDecl *FD = getUnionField()) {
522f4a2713aSLionel Sambuc Out << "." << *FD << " = ";
523f4a2713aSLionel Sambuc getUnionValue().printPretty(Out, Ctx, FD->getType());
524f4a2713aSLionel Sambuc }
525f4a2713aSLionel Sambuc Out << '}';
526f4a2713aSLionel Sambuc return;
527f4a2713aSLionel Sambuc case APValue::MemberPointer:
528f4a2713aSLionel Sambuc // FIXME: This is not enough to unambiguously identify the member in a
529f4a2713aSLionel Sambuc // multiple-inheritance scenario.
530f4a2713aSLionel Sambuc if (const ValueDecl *VD = getMemberPointerDecl()) {
531f4a2713aSLionel Sambuc Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;
532f4a2713aSLionel Sambuc return;
533f4a2713aSLionel Sambuc }
534f4a2713aSLionel Sambuc Out << "0";
535f4a2713aSLionel Sambuc return;
536f4a2713aSLionel Sambuc case APValue::AddrLabelDiff:
537f4a2713aSLionel Sambuc Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName();
538f4a2713aSLionel Sambuc Out << " - ";
539f4a2713aSLionel Sambuc Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName();
540f4a2713aSLionel Sambuc return;
541f4a2713aSLionel Sambuc }
542f4a2713aSLionel Sambuc llvm_unreachable("Unknown APValue kind!");
543f4a2713aSLionel Sambuc }
544f4a2713aSLionel Sambuc
getAsString(ASTContext & Ctx,QualType Ty) const545f4a2713aSLionel Sambuc std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const {
546f4a2713aSLionel Sambuc std::string Result;
547f4a2713aSLionel Sambuc llvm::raw_string_ostream Out(Result);
548f4a2713aSLionel Sambuc printPretty(Out, Ctx, Ty);
549f4a2713aSLionel Sambuc Out.flush();
550f4a2713aSLionel Sambuc return Result;
551f4a2713aSLionel Sambuc }
552f4a2713aSLionel Sambuc
getLValueBase() const553f4a2713aSLionel Sambuc const APValue::LValueBase APValue::getLValueBase() const {
554f4a2713aSLionel Sambuc assert(isLValue() && "Invalid accessor");
555*0a6a1f1dSLionel Sambuc return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getPointer();
556f4a2713aSLionel Sambuc }
557f4a2713aSLionel Sambuc
isLValueOnePastTheEnd() const558f4a2713aSLionel Sambuc bool APValue::isLValueOnePastTheEnd() const {
559f4a2713aSLionel Sambuc assert(isLValue() && "Invalid accessor");
560*0a6a1f1dSLionel Sambuc return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getInt();
561f4a2713aSLionel Sambuc }
562f4a2713aSLionel Sambuc
getLValueOffset()563f4a2713aSLionel Sambuc CharUnits &APValue::getLValueOffset() {
564f4a2713aSLionel Sambuc assert(isLValue() && "Invalid accessor");
565*0a6a1f1dSLionel Sambuc return ((LV*)(void*)Data.buffer)->Offset;
566f4a2713aSLionel Sambuc }
567f4a2713aSLionel Sambuc
hasLValuePath() const568f4a2713aSLionel Sambuc bool APValue::hasLValuePath() const {
569f4a2713aSLionel Sambuc assert(isLValue() && "Invalid accessor");
570*0a6a1f1dSLionel Sambuc return ((const LV*)(const char*)Data.buffer)->hasPath();
571f4a2713aSLionel Sambuc }
572f4a2713aSLionel Sambuc
getLValuePath() const573f4a2713aSLionel Sambuc ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
574f4a2713aSLionel Sambuc assert(isLValue() && hasLValuePath() && "Invalid accessor");
575*0a6a1f1dSLionel Sambuc const LV &LVal = *((const LV*)(const char*)Data.buffer);
576*0a6a1f1dSLionel Sambuc return llvm::makeArrayRef(LVal.getPath(), LVal.PathLength);
577f4a2713aSLionel Sambuc }
578f4a2713aSLionel Sambuc
getLValueCallIndex() const579f4a2713aSLionel Sambuc unsigned APValue::getLValueCallIndex() const {
580f4a2713aSLionel Sambuc assert(isLValue() && "Invalid accessor");
581*0a6a1f1dSLionel Sambuc return ((const LV*)(const char*)Data.buffer)->CallIndex;
582f4a2713aSLionel Sambuc }
583f4a2713aSLionel Sambuc
setLValue(LValueBase B,const CharUnits & O,NoLValuePath,unsigned CallIndex)584f4a2713aSLionel Sambuc void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
585f4a2713aSLionel Sambuc unsigned CallIndex) {
586f4a2713aSLionel Sambuc assert(isLValue() && "Invalid accessor");
587*0a6a1f1dSLionel Sambuc LV &LVal = *((LV*)(char*)Data.buffer);
588f4a2713aSLionel Sambuc LVal.BaseAndIsOnePastTheEnd.setPointer(B);
589f4a2713aSLionel Sambuc LVal.BaseAndIsOnePastTheEnd.setInt(false);
590f4a2713aSLionel Sambuc LVal.Offset = O;
591f4a2713aSLionel Sambuc LVal.CallIndex = CallIndex;
592f4a2713aSLionel Sambuc LVal.resizePath((unsigned)-1);
593f4a2713aSLionel Sambuc }
594f4a2713aSLionel Sambuc
setLValue(LValueBase B,const CharUnits & O,ArrayRef<LValuePathEntry> Path,bool IsOnePastTheEnd,unsigned CallIndex)595f4a2713aSLionel Sambuc void APValue::setLValue(LValueBase B, const CharUnits &O,
596f4a2713aSLionel Sambuc ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
597f4a2713aSLionel Sambuc unsigned CallIndex) {
598f4a2713aSLionel Sambuc assert(isLValue() && "Invalid accessor");
599*0a6a1f1dSLionel Sambuc LV &LVal = *((LV*)(char*)Data.buffer);
600f4a2713aSLionel Sambuc LVal.BaseAndIsOnePastTheEnd.setPointer(B);
601f4a2713aSLionel Sambuc LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd);
602f4a2713aSLionel Sambuc LVal.Offset = O;
603f4a2713aSLionel Sambuc LVal.CallIndex = CallIndex;
604f4a2713aSLionel Sambuc LVal.resizePath(Path.size());
605f4a2713aSLionel Sambuc memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
606f4a2713aSLionel Sambuc }
607f4a2713aSLionel Sambuc
getMemberPointerDecl() const608f4a2713aSLionel Sambuc const ValueDecl *APValue::getMemberPointerDecl() const {
609f4a2713aSLionel Sambuc assert(isMemberPointer() && "Invalid accessor");
610*0a6a1f1dSLionel Sambuc const MemberPointerData &MPD =
611*0a6a1f1dSLionel Sambuc *((const MemberPointerData *)(const char *)Data.buffer);
612f4a2713aSLionel Sambuc return MPD.MemberAndIsDerivedMember.getPointer();
613f4a2713aSLionel Sambuc }
614f4a2713aSLionel Sambuc
isMemberPointerToDerivedMember() const615f4a2713aSLionel Sambuc bool APValue::isMemberPointerToDerivedMember() const {
616f4a2713aSLionel Sambuc assert(isMemberPointer() && "Invalid accessor");
617*0a6a1f1dSLionel Sambuc const MemberPointerData &MPD =
618*0a6a1f1dSLionel Sambuc *((const MemberPointerData *)(const char *)Data.buffer);
619f4a2713aSLionel Sambuc return MPD.MemberAndIsDerivedMember.getInt();
620f4a2713aSLionel Sambuc }
621f4a2713aSLionel Sambuc
getMemberPointerPath() const622f4a2713aSLionel Sambuc ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {
623f4a2713aSLionel Sambuc assert(isMemberPointer() && "Invalid accessor");
624*0a6a1f1dSLionel Sambuc const MemberPointerData &MPD =
625*0a6a1f1dSLionel Sambuc *((const MemberPointerData *)(const char *)Data.buffer);
626*0a6a1f1dSLionel Sambuc return llvm::makeArrayRef(MPD.getPath(), MPD.PathLength);
627f4a2713aSLionel Sambuc }
628f4a2713aSLionel Sambuc
MakeLValue()629f4a2713aSLionel Sambuc void APValue::MakeLValue() {
630f4a2713aSLionel Sambuc assert(isUninit() && "Bad state change");
631*0a6a1f1dSLionel Sambuc static_assert(sizeof(LV) <= DataSize, "LV too big");
632*0a6a1f1dSLionel Sambuc new ((void*)(char*)Data.buffer) LV();
633f4a2713aSLionel Sambuc Kind = LValue;
634f4a2713aSLionel Sambuc }
635f4a2713aSLionel Sambuc
MakeArray(unsigned InitElts,unsigned Size)636f4a2713aSLionel Sambuc void APValue::MakeArray(unsigned InitElts, unsigned Size) {
637f4a2713aSLionel Sambuc assert(isUninit() && "Bad state change");
638*0a6a1f1dSLionel Sambuc new ((void*)(char*)Data.buffer) Arr(InitElts, Size);
639f4a2713aSLionel Sambuc Kind = Array;
640f4a2713aSLionel Sambuc }
641f4a2713aSLionel Sambuc
MakeMemberPointer(const ValueDecl * Member,bool IsDerivedMember,ArrayRef<const CXXRecordDecl * > Path)642f4a2713aSLionel Sambuc void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
643f4a2713aSLionel Sambuc ArrayRef<const CXXRecordDecl*> Path) {
644f4a2713aSLionel Sambuc assert(isUninit() && "Bad state change");
645*0a6a1f1dSLionel Sambuc MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData;
646f4a2713aSLionel Sambuc Kind = MemberPointer;
647f4a2713aSLionel Sambuc MPD->MemberAndIsDerivedMember.setPointer(Member);
648f4a2713aSLionel Sambuc MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
649f4a2713aSLionel Sambuc MPD->resizePath(Path.size());
650f4a2713aSLionel Sambuc memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));
651f4a2713aSLionel Sambuc }
652