1193326Sed//===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file implements the APValue class.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#include "clang/AST/APValue.h"
15234353Sdim#include "clang/AST/ASTContext.h"
16202379Srdivacky#include "clang/AST/CharUnits.h"
17234353Sdim#include "clang/AST/DeclCXX.h"
18234353Sdim#include "clang/AST/Expr.h"
19234353Sdim#include "clang/AST/Type.h"
20226633Sdim#include "clang/Basic/Diagnostic.h"
21226633Sdim#include "llvm/ADT/SmallString.h"
22249423Sdim#include "llvm/Support/ErrorHandling.h"
23193326Sed#include "llvm/Support/raw_ostream.h"
24193326Sedusing namespace clang;
25193326Sed
26202379Srdivackynamespace {
27234353Sdim  struct LVBase {
28234353Sdim    llvm::PointerIntPair<APValue::LValueBase, 1, bool> BaseAndIsOnePastTheEnd;
29202379Srdivacky    CharUnits Offset;
30234353Sdim    unsigned PathLength;
31234353Sdim    unsigned CallIndex;
32202379Srdivacky  };
33202379Srdivacky}
34193326Sed
35234353Sdimstruct APValue::LV : LVBase {
36234353Sdim  static const unsigned InlinePathSpace =
37234353Sdim      (MaxSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
38234353Sdim
39234353Sdim  /// Path - The sequence of base classes, fields and array indices to follow to
40234353Sdim  /// walk from Base to the subobject. When performing GCC-style folding, there
41234353Sdim  /// may not be such a path.
42234353Sdim  union {
43234353Sdim    LValuePathEntry Path[InlinePathSpace];
44234353Sdim    LValuePathEntry *PathPtr;
45234353Sdim  };
46234353Sdim
47234353Sdim  LV() { PathLength = (unsigned)-1; }
48234353Sdim  ~LV() { resizePath(0); }
49234353Sdim
50234353Sdim  void resizePath(unsigned Length) {
51234353Sdim    if (Length == PathLength)
52234353Sdim      return;
53234353Sdim    if (hasPathPtr())
54234353Sdim      delete [] PathPtr;
55234353Sdim    PathLength = Length;
56234353Sdim    if (hasPathPtr())
57234353Sdim      PathPtr = new LValuePathEntry[Length];
58234353Sdim  }
59234353Sdim
60234353Sdim  bool hasPath() const { return PathLength != (unsigned)-1; }
61234353Sdim  bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }
62234353Sdim
63234353Sdim  LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }
64234353Sdim  const LValuePathEntry *getPath() const {
65234353Sdim    return hasPathPtr() ? PathPtr : Path;
66234353Sdim  }
67234353Sdim};
68234353Sdim
69234353Sdimnamespace {
70234353Sdim  struct MemberPointerBase {
71234353Sdim    llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember;
72234353Sdim    unsigned PathLength;
73234353Sdim  };
74202379Srdivacky}
75202379Srdivacky
76234353Sdimstruct APValue::MemberPointerData : MemberPointerBase {
77234353Sdim  static const unsigned InlinePathSpace =
78234353Sdim      (MaxSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*);
79234353Sdim  typedef const CXXRecordDecl *PathElem;
80234353Sdim  union {
81234353Sdim    PathElem Path[InlinePathSpace];
82234353Sdim    PathElem *PathPtr;
83234353Sdim  };
84234353Sdim
85234353Sdim  MemberPointerData() { PathLength = 0; }
86234353Sdim  ~MemberPointerData() { resizePath(0); }
87234353Sdim
88234353Sdim  void resizePath(unsigned Length) {
89234353Sdim    if (Length == PathLength)
90234353Sdim      return;
91234353Sdim    if (hasPathPtr())
92234353Sdim      delete [] PathPtr;
93234353Sdim    PathLength = Length;
94234353Sdim    if (hasPathPtr())
95234353Sdim      PathPtr = new PathElem[Length];
96193326Sed  }
97234353Sdim
98234353Sdim  bool hasPathPtr() const { return PathLength > InlinePathSpace; }
99234353Sdim
100234353Sdim  PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; }
101234353Sdim  const PathElem *getPath() const {
102234353Sdim    return hasPathPtr() ? PathPtr : Path;
103234353Sdim  }
104234353Sdim};
105234353Sdim
106234353Sdim// FIXME: Reduce the malloc traffic here.
107234353Sdim
108234353SdimAPValue::Arr::Arr(unsigned NumElts, unsigned Size) :
109234353Sdim  Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]),
110234353Sdim  NumElts(NumElts), ArrSize(Size) {}
111234353SdimAPValue::Arr::~Arr() { delete [] Elts; }
112234353Sdim
113234353SdimAPValue::StructData::StructData(unsigned NumBases, unsigned NumFields) :
114234353Sdim  Elts(new APValue[NumBases+NumFields]),
115234353Sdim  NumBases(NumBases), NumFields(NumFields) {}
116234353SdimAPValue::StructData::~StructData() {
117234353Sdim  delete [] Elts;
118234353Sdim}
119234353Sdim
120234353SdimAPValue::UnionData::UnionData() : Field(0), Value(new APValue) {}
121234353SdimAPValue::UnionData::~UnionData () {
122234353Sdim  delete Value;
123234353Sdim}
124234353Sdim
125234353SdimAPValue::APValue(const APValue &RHS) : Kind(Uninitialized) {
126234353Sdim  switch (RHS.getKind()) {
127234353Sdim  case Uninitialized:
128234353Sdim    break;
129234353Sdim  case Int:
130234353Sdim    MakeInt();
131193326Sed    setInt(RHS.getInt());
132234353Sdim    break;
133234353Sdim  case Float:
134234353Sdim    MakeFloat();
135193326Sed    setFloat(RHS.getFloat());
136234353Sdim    break;
137234353Sdim  case Vector:
138234353Sdim    MakeVector();
139207619Srdivacky    setVector(((const Vec *)(const char *)RHS.Data)->Elts,
140207619Srdivacky              RHS.getVectorLength());
141234353Sdim    break;
142234353Sdim  case ComplexInt:
143234353Sdim    MakeComplexInt();
144193326Sed    setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
145234353Sdim    break;
146234353Sdim  case ComplexFloat:
147234353Sdim    MakeComplexFloat();
148193326Sed    setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
149234353Sdim    break;
150234353Sdim  case LValue:
151234353Sdim    MakeLValue();
152234353Sdim    if (RHS.hasLValuePath())
153234353Sdim      setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
154234353Sdim                RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex());
155234353Sdim    else
156234353Sdim      setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
157234353Sdim                RHS.getLValueCallIndex());
158234353Sdim    break;
159234353Sdim  case Array:
160234353Sdim    MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
161234353Sdim    for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)
162234353Sdim      getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);
163234353Sdim    if (RHS.hasArrayFiller())
164234353Sdim      getArrayFiller() = RHS.getArrayFiller();
165234353Sdim    break;
166234353Sdim  case Struct:
167234353Sdim    MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());
168234353Sdim    for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I)
169234353Sdim      getStructBase(I) = RHS.getStructBase(I);
170234353Sdim    for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I)
171234353Sdim      getStructField(I) = RHS.getStructField(I);
172234353Sdim    break;
173234353Sdim  case Union:
174234353Sdim    MakeUnion();
175234353Sdim    setUnion(RHS.getUnionField(), RHS.getUnionValue());
176234353Sdim    break;
177234353Sdim  case MemberPointer:
178234353Sdim    MakeMemberPointer(RHS.getMemberPointerDecl(),
179234353Sdim                      RHS.isMemberPointerToDerivedMember(),
180234353Sdim                      RHS.getMemberPointerPath());
181234353Sdim    break;
182234353Sdim  case AddrLabelDiff:
183234353Sdim    MakeAddrLabelDiff();
184234353Sdim    setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS());
185234353Sdim    break;
186234353Sdim  }
187193326Sed}
188193326Sed
189234353Sdimvoid APValue::DestroyDataAndMakeUninit() {
190193326Sed  if (Kind == Int)
191198092Srdivacky    ((APSInt*)(char*)Data)->~APSInt();
192193326Sed  else if (Kind == Float)
193198092Srdivacky    ((APFloat*)(char*)Data)->~APFloat();
194193326Sed  else if (Kind == Vector)
195198092Srdivacky    ((Vec*)(char*)Data)->~Vec();
196193326Sed  else if (Kind == ComplexInt)
197198092Srdivacky    ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
198193326Sed  else if (Kind == ComplexFloat)
199198092Srdivacky    ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
200234353Sdim  else if (Kind == LValue)
201198092Srdivacky    ((LV*)(char*)Data)->~LV();
202234353Sdim  else if (Kind == Array)
203234353Sdim    ((Arr*)(char*)Data)->~Arr();
204234353Sdim  else if (Kind == Struct)
205234353Sdim    ((StructData*)(char*)Data)->~StructData();
206234353Sdim  else if (Kind == Union)
207234353Sdim    ((UnionData*)(char*)Data)->~UnionData();
208234353Sdim  else if (Kind == MemberPointer)
209234353Sdim    ((MemberPointerData*)(char*)Data)->~MemberPointerData();
210234353Sdim  else if (Kind == AddrLabelDiff)
211234353Sdim    ((AddrLabelDiffData*)(char*)Data)->~AddrLabelDiffData();
212193326Sed  Kind = Uninitialized;
213193326Sed}
214193326Sed
215263508Sdimbool APValue::needsCleanup() const {
216263508Sdim  switch (getKind()) {
217263508Sdim  case Uninitialized:
218263508Sdim  case AddrLabelDiff:
219263508Sdim    return false;
220263508Sdim  case Struct:
221263508Sdim  case Union:
222263508Sdim  case Array:
223263508Sdim  case Vector:
224263508Sdim    return true;
225263508Sdim  case Int:
226263508Sdim    return getInt().needsCleanup();
227263508Sdim  case Float:
228263508Sdim    return getFloat().needsCleanup();
229263508Sdim  case ComplexFloat:
230263508Sdim    assert(getComplexFloatImag().needsCleanup() ==
231263508Sdim               getComplexFloatReal().needsCleanup() &&
232263508Sdim           "In _Complex float types, real and imaginary values always have the "
233263508Sdim           "same size.");
234263508Sdim    return getComplexFloatReal().needsCleanup();
235263508Sdim  case ComplexInt:
236263508Sdim    assert(getComplexIntImag().needsCleanup() ==
237263508Sdim               getComplexIntReal().needsCleanup() &&
238263508Sdim           "In _Complex int types, real and imaginary values must have the "
239263508Sdim           "same size.");
240263508Sdim    return getComplexIntReal().needsCleanup();
241263508Sdim  case LValue:
242263508Sdim    return reinterpret_cast<const LV *>(Data)->hasPathPtr();
243263508Sdim  case MemberPointer:
244263508Sdim    return reinterpret_cast<const MemberPointerData *>(Data)->hasPathPtr();
245263508Sdim  }
246263508Sdim  llvm_unreachable("Unknown APValue kind!");
247263508Sdim}
248263508Sdim
249234353Sdimvoid APValue::swap(APValue &RHS) {
250234353Sdim  std::swap(Kind, RHS.Kind);
251234353Sdim  char TmpData[MaxSize];
252234353Sdim  memcpy(TmpData, Data, MaxSize);
253234353Sdim  memcpy(Data, RHS.Data, MaxSize);
254234353Sdim  memcpy(RHS.Data, TmpData, MaxSize);
255234353Sdim}
256234353Sdim
257193326Sedvoid APValue::dump() const {
258234353Sdim  dump(llvm::errs());
259193326Sed  llvm::errs() << '\n';
260193326Sed}
261193326Sed
262193326Sedstatic double GetApproxValue(const llvm::APFloat &F) {
263193326Sed  llvm::APFloat V = F;
264193326Sed  bool ignored;
265193326Sed  V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
266193326Sed            &ignored);
267193326Sed  return V.convertToDouble();
268193326Sed}
269193326Sed
270234353Sdimvoid APValue::dump(raw_ostream &OS) const {
271193326Sed  switch (getKind()) {
272193326Sed  case Uninitialized:
273193326Sed    OS << "Uninitialized";
274193326Sed    return;
275193326Sed  case Int:
276193326Sed    OS << "Int: " << getInt();
277193326Sed    return;
278193326Sed  case Float:
279193326Sed    OS << "Float: " << GetApproxValue(getFloat());
280193326Sed    return;
281193326Sed  case Vector:
282234353Sdim    OS << "Vector: ";
283234353Sdim    getVectorElt(0).dump(OS);
284234353Sdim    for (unsigned i = 1; i != getVectorLength(); ++i) {
285234353Sdim      OS << ", ";
286234353Sdim      getVectorElt(i).dump(OS);
287234353Sdim    }
288193326Sed    return;
289193326Sed  case ComplexInt:
290193326Sed    OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
291193326Sed    return;
292193326Sed  case ComplexFloat:
293193326Sed    OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
294193326Sed       << ", " << GetApproxValue(getComplexFloatImag());
295234353Sdim    return;
296193326Sed  case LValue:
297193326Sed    OS << "LValue: <todo>";
298193326Sed    return;
299234353Sdim  case Array:
300234353Sdim    OS << "Array: ";
301234353Sdim    for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
302234353Sdim      getArrayInitializedElt(I).dump(OS);
303234353Sdim      if (I != getArraySize() - 1) OS << ", ";
304234353Sdim    }
305234353Sdim    if (hasArrayFiller()) {
306234353Sdim      OS << getArraySize() - getArrayInitializedElts() << " x ";
307234353Sdim      getArrayFiller().dump(OS);
308234353Sdim    }
309234353Sdim    return;
310234353Sdim  case Struct:
311234353Sdim    OS << "Struct ";
312234353Sdim    if (unsigned N = getStructNumBases()) {
313234353Sdim      OS << " bases: ";
314234353Sdim      getStructBase(0).dump(OS);
315234353Sdim      for (unsigned I = 1; I != N; ++I) {
316234353Sdim        OS << ", ";
317234353Sdim        getStructBase(I).dump(OS);
318234353Sdim      }
319234353Sdim    }
320234353Sdim    if (unsigned N = getStructNumFields()) {
321234353Sdim      OS << " fields: ";
322234353Sdim      getStructField(0).dump(OS);
323234353Sdim      for (unsigned I = 1; I != N; ++I) {
324234353Sdim        OS << ", ";
325234353Sdim        getStructField(I).dump(OS);
326234353Sdim      }
327234353Sdim    }
328234353Sdim    return;
329234353Sdim  case Union:
330234353Sdim    OS << "Union: ";
331234353Sdim    getUnionValue().dump(OS);
332234353Sdim    return;
333234353Sdim  case MemberPointer:
334234353Sdim    OS << "MemberPointer: <todo>";
335234353Sdim    return;
336234353Sdim  case AddrLabelDiff:
337234353Sdim    OS << "AddrLabelDiff: <todo>";
338234353Sdim    return;
339193326Sed  }
340234353Sdim  llvm_unreachable("Unknown APValue kind!");
341193326Sed}
342193326Sed
343234353Sdimvoid APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{
344234353Sdim  switch (getKind()) {
345226633Sdim  case APValue::Uninitialized:
346234353Sdim    Out << "<uninitialized>";
347234353Sdim    return;
348226633Sdim  case APValue::Int:
349234353Sdim    if (Ty->isBooleanType())
350234353Sdim      Out << (getInt().getBoolValue() ? "true" : "false");
351234353Sdim    else
352234353Sdim      Out << getInt();
353234353Sdim    return;
354226633Sdim  case APValue::Float:
355234353Sdim    Out << GetApproxValue(getFloat());
356234353Sdim    return;
357234353Sdim  case APValue::Vector: {
358234353Sdim    Out << '{';
359234353Sdim    QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
360234353Sdim    getVectorElt(0).printPretty(Out, Ctx, ElemTy);
361234353Sdim    for (unsigned i = 1; i != getVectorLength(); ++i) {
362226633Sdim      Out << ", ";
363234353Sdim      getVectorElt(i).printPretty(Out, Ctx, ElemTy);
364226633Sdim    }
365234353Sdim    Out << '}';
366234353Sdim    return;
367234353Sdim  }
368226633Sdim  case APValue::ComplexInt:
369234353Sdim    Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";
370234353Sdim    return;
371226633Sdim  case APValue::ComplexFloat:
372234353Sdim    Out << GetApproxValue(getComplexFloatReal()) << "+"
373234353Sdim        << GetApproxValue(getComplexFloatImag()) << "i";
374234353Sdim    return;
375234353Sdim  case APValue::LValue: {
376234353Sdim    LValueBase Base = getLValueBase();
377234353Sdim    if (!Base) {
378234353Sdim      Out << "0";
379234353Sdim      return;
380234353Sdim    }
381234353Sdim
382234353Sdim    bool IsReference = Ty->isReferenceType();
383234353Sdim    QualType InnerTy
384234353Sdim      = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();
385249423Sdim    if (InnerTy.isNull())
386249423Sdim      InnerTy = Ty;
387234353Sdim
388234353Sdim    if (!hasLValuePath()) {
389234353Sdim      // No lvalue path: just print the offset.
390234353Sdim      CharUnits O = getLValueOffset();
391234353Sdim      CharUnits S = Ctx.getTypeSizeInChars(InnerTy);
392234353Sdim      if (!O.isZero()) {
393234353Sdim        if (IsReference)
394234353Sdim          Out << "*(";
395234353Sdim        if (O % S) {
396234353Sdim          Out << "(char*)";
397234353Sdim          S = CharUnits::One();
398234353Sdim        }
399234353Sdim        Out << '&';
400234353Sdim      } else if (!IsReference)
401234353Sdim        Out << '&';
402234353Sdim
403234353Sdim      if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
404234353Sdim        Out << *VD;
405234353Sdim      else
406239462Sdim        Base.get<const Expr*>()->printPretty(Out, 0, Ctx.getPrintingPolicy());
407234353Sdim      if (!O.isZero()) {
408234353Sdim        Out << " + " << (O / S);
409234353Sdim        if (IsReference)
410234353Sdim          Out << ')';
411234353Sdim      }
412234353Sdim      return;
413234353Sdim    }
414234353Sdim
415234353Sdim    // We have an lvalue path. Print it out nicely.
416234353Sdim    if (!IsReference)
417234353Sdim      Out << '&';
418234353Sdim    else if (isLValueOnePastTheEnd())
419234353Sdim      Out << "*(&";
420234353Sdim
421234353Sdim    QualType ElemTy;
422234353Sdim    if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
423234353Sdim      Out << *VD;
424234353Sdim      ElemTy = VD->getType();
425234353Sdim    } else {
426234353Sdim      const Expr *E = Base.get<const Expr*>();
427239462Sdim      E->printPretty(Out, 0, Ctx.getPrintingPolicy());
428234353Sdim      ElemTy = E->getType();
429234353Sdim    }
430234353Sdim
431234353Sdim    ArrayRef<LValuePathEntry> Path = getLValuePath();
432234353Sdim    const CXXRecordDecl *CastToBase = 0;
433234353Sdim    for (unsigned I = 0, N = Path.size(); I != N; ++I) {
434234353Sdim      if (ElemTy->getAs<RecordType>()) {
435234353Sdim        // The lvalue refers to a class type, so the next path entry is a base
436234353Sdim        // or member.
437234353Sdim        const Decl *BaseOrMember =
438234353Sdim        BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer();
439234353Sdim        if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
440234353Sdim          CastToBase = RD;
441234353Sdim          ElemTy = Ctx.getRecordType(RD);
442234353Sdim        } else {
443234353Sdim          const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
444234353Sdim          Out << ".";
445234353Sdim          if (CastToBase)
446234353Sdim            Out << *CastToBase << "::";
447234353Sdim          Out << *VD;
448234353Sdim          ElemTy = VD->getType();
449234353Sdim        }
450234353Sdim      } else {
451234353Sdim        // The lvalue must refer to an array.
452234353Sdim        Out << '[' << Path[I].ArrayIndex << ']';
453234353Sdim        ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType();
454234353Sdim      }
455234353Sdim    }
456234353Sdim
457234353Sdim    // Handle formatting of one-past-the-end lvalues.
458234353Sdim    if (isLValueOnePastTheEnd()) {
459234353Sdim      // FIXME: If CastToBase is non-0, we should prefix the output with
460234353Sdim      // "(CastToBase*)".
461234353Sdim      Out << " + 1";
462234353Sdim      if (IsReference)
463234353Sdim        Out << ')';
464234353Sdim    }
465234353Sdim    return;
466226633Sdim  }
467234353Sdim  case APValue::Array: {
468234353Sdim    const ArrayType *AT = Ctx.getAsArrayType(Ty);
469234353Sdim    QualType ElemTy = AT->getElementType();
470234353Sdim    Out << '{';
471234353Sdim    if (unsigned N = getArrayInitializedElts()) {
472234353Sdim      getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy);
473234353Sdim      for (unsigned I = 1; I != N; ++I) {
474234353Sdim        Out << ", ";
475234353Sdim        if (I == 10) {
476234353Sdim          // Avoid printing out the entire contents of large arrays.
477234353Sdim          Out << "...";
478234353Sdim          break;
479234353Sdim        }
480234353Sdim        getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy);
481234353Sdim      }
482234353Sdim    }
483234353Sdim    Out << '}';
484234353Sdim    return;
485234353Sdim  }
486234353Sdim  case APValue::Struct: {
487234353Sdim    Out << '{';
488234353Sdim    const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
489234353Sdim    bool First = true;
490234353Sdim    if (unsigned N = getStructNumBases()) {
491234353Sdim      const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
492234353Sdim      CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
493234353Sdim      for (unsigned I = 0; I != N; ++I, ++BI) {
494234353Sdim        assert(BI != CD->bases_end());
495234353Sdim        if (!First)
496234353Sdim          Out << ", ";
497234353Sdim        getStructBase(I).printPretty(Out, Ctx, BI->getType());
498234353Sdim        First = false;
499234353Sdim      }
500234353Sdim    }
501234353Sdim    for (RecordDecl::field_iterator FI = RD->field_begin();
502234353Sdim         FI != RD->field_end(); ++FI) {
503234353Sdim      if (!First)
504234353Sdim        Out << ", ";
505239462Sdim      if (FI->isUnnamedBitfield()) continue;
506239462Sdim      getStructField(FI->getFieldIndex()).
507239462Sdim        printPretty(Out, Ctx, FI->getType());
508234353Sdim      First = false;
509234353Sdim    }
510234353Sdim    Out << '}';
511234353Sdim    return;
512234353Sdim  }
513234353Sdim  case APValue::Union:
514234353Sdim    Out << '{';
515234353Sdim    if (const FieldDecl *FD = getUnionField()) {
516234353Sdim      Out << "." << *FD << " = ";
517234353Sdim      getUnionValue().printPretty(Out, Ctx, FD->getType());
518234353Sdim    }
519234353Sdim    Out << '}';
520234353Sdim    return;
521234353Sdim  case APValue::MemberPointer:
522234353Sdim    // FIXME: This is not enough to unambiguously identify the member in a
523234353Sdim    // multiple-inheritance scenario.
524234353Sdim    if (const ValueDecl *VD = getMemberPointerDecl()) {
525234353Sdim      Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;
526234353Sdim      return;
527234353Sdim    }
528234353Sdim    Out << "0";
529234353Sdim    return;
530234353Sdim  case APValue::AddrLabelDiff:
531234353Sdim    Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName();
532234353Sdim    Out << " - ";
533234353Sdim    Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName();
534234353Sdim    return;
535234353Sdim  }
536234353Sdim  llvm_unreachable("Unknown APValue kind!");
537226633Sdim}
538226633Sdim
539234353Sdimstd::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const {
540234353Sdim  std::string Result;
541234353Sdim  llvm::raw_string_ostream Out(Result);
542234353Sdim  printPretty(Out, Ctx, Ty);
543234353Sdim  Out.flush();
544234353Sdim  return Result;
545226633Sdim}
546226633Sdim
547234353Sdimconst APValue::LValueBase APValue::getLValueBase() const {
548202379Srdivacky  assert(isLValue() && "Invalid accessor");
549234353Sdim  return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getPointer();
550202379Srdivacky}
551202379Srdivacky
552234353Sdimbool APValue::isLValueOnePastTheEnd() const {
553234353Sdim  assert(isLValue() && "Invalid accessor");
554234353Sdim  return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getInt();
555202379Srdivacky}
556202379Srdivacky
557234353SdimCharUnits &APValue::getLValueOffset() {
558202379Srdivacky  assert(isLValue() && "Invalid accessor");
559234353Sdim  return ((LV*)(void*)Data)->Offset;
560202379Srdivacky}
561202379Srdivacky
562234353Sdimbool APValue::hasLValuePath() const {
563234353Sdim  assert(isLValue() && "Invalid accessor");
564234353Sdim  return ((const LV*)(const char*)Data)->hasPath();
565234353Sdim}
566234353Sdim
567234353SdimArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
568234353Sdim  assert(isLValue() && hasLValuePath() && "Invalid accessor");
569234353Sdim  const LV &LVal = *((const LV*)(const char*)Data);
570234353Sdim  return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
571234353Sdim}
572234353Sdim
573234353Sdimunsigned APValue::getLValueCallIndex() const {
574234353Sdim  assert(isLValue() && "Invalid accessor");
575234353Sdim  return ((const LV*)(const char*)Data)->CallIndex;
576234353Sdim}
577234353Sdim
578234353Sdimvoid APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
579234353Sdim                        unsigned CallIndex) {
580234353Sdim  assert(isLValue() && "Invalid accessor");
581234353Sdim  LV &LVal = *((LV*)(char*)Data);
582234353Sdim  LVal.BaseAndIsOnePastTheEnd.setPointer(B);
583234353Sdim  LVal.BaseAndIsOnePastTheEnd.setInt(false);
584234353Sdim  LVal.Offset = O;
585234353Sdim  LVal.CallIndex = CallIndex;
586234353Sdim  LVal.resizePath((unsigned)-1);
587234353Sdim}
588234353Sdim
589234353Sdimvoid APValue::setLValue(LValueBase B, const CharUnits &O,
590234353Sdim                        ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
591234353Sdim                        unsigned CallIndex) {
592234353Sdim  assert(isLValue() && "Invalid accessor");
593234353Sdim  LV &LVal = *((LV*)(char*)Data);
594234353Sdim  LVal.BaseAndIsOnePastTheEnd.setPointer(B);
595234353Sdim  LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd);
596234353Sdim  LVal.Offset = O;
597234353Sdim  LVal.CallIndex = CallIndex;
598234353Sdim  LVal.resizePath(Path.size());
599234353Sdim  memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
600234353Sdim}
601234353Sdim
602234353Sdimconst ValueDecl *APValue::getMemberPointerDecl() const {
603234353Sdim  assert(isMemberPointer() && "Invalid accessor");
604234353Sdim  const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
605234353Sdim  return MPD.MemberAndIsDerivedMember.getPointer();
606234353Sdim}
607234353Sdim
608234353Sdimbool APValue::isMemberPointerToDerivedMember() const {
609234353Sdim  assert(isMemberPointer() && "Invalid accessor");
610234353Sdim  const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
611234353Sdim  return MPD.MemberAndIsDerivedMember.getInt();
612234353Sdim}
613234353Sdim
614234353SdimArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {
615234353Sdim  assert(isMemberPointer() && "Invalid accessor");
616234353Sdim  const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
617234353Sdim  return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength);
618234353Sdim}
619234353Sdim
620202379Srdivackyvoid APValue::MakeLValue() {
621202379Srdivacky  assert(isUninit() && "Bad state change");
622234353Sdim  assert(sizeof(LV) <= MaxSize && "LV too big");
623202379Srdivacky  new ((void*)(char*)Data) LV();
624202379Srdivacky  Kind = LValue;
625202379Srdivacky}
626202379Srdivacky
627234353Sdimvoid APValue::MakeArray(unsigned InitElts, unsigned Size) {
628234353Sdim  assert(isUninit() && "Bad state change");
629234353Sdim  new ((void*)(char*)Data) Arr(InitElts, Size);
630234353Sdim  Kind = Array;
631234353Sdim}
632234353Sdim
633234353Sdimvoid APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
634234353Sdim                                ArrayRef<const CXXRecordDecl*> Path) {
635234353Sdim  assert(isUninit() && "Bad state change");
636234353Sdim  MemberPointerData *MPD = new ((void*)(char*)Data) MemberPointerData;
637234353Sdim  Kind = MemberPointer;
638234353Sdim  MPD->MemberAndIsDerivedMember.setPointer(Member);
639234353Sdim  MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
640234353Sdim  MPD->resizePath(Path.size());
641234353Sdim  memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));
642234353Sdim}
643