APValue.cpp revision 234353
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"
22193326Sed#include "llvm/Support/raw_ostream.h"
23226633Sdim#include "llvm/Support/ErrorHandling.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
215234353Sdimvoid APValue::swap(APValue &RHS) {
216234353Sdim  std::swap(Kind, RHS.Kind);
217234353Sdim  char TmpData[MaxSize];
218234353Sdim  memcpy(TmpData, Data, MaxSize);
219234353Sdim  memcpy(Data, RHS.Data, MaxSize);
220234353Sdim  memcpy(RHS.Data, TmpData, MaxSize);
221234353Sdim}
222234353Sdim
223193326Sedvoid APValue::dump() const {
224234353Sdim  dump(llvm::errs());
225193326Sed  llvm::errs() << '\n';
226193326Sed}
227193326Sed
228193326Sedstatic double GetApproxValue(const llvm::APFloat &F) {
229193326Sed  llvm::APFloat V = F;
230193326Sed  bool ignored;
231193326Sed  V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
232193326Sed            &ignored);
233193326Sed  return V.convertToDouble();
234193326Sed}
235193326Sed
236234353Sdimvoid APValue::dump(raw_ostream &OS) const {
237193326Sed  switch (getKind()) {
238193326Sed  case Uninitialized:
239193326Sed    OS << "Uninitialized";
240193326Sed    return;
241193326Sed  case Int:
242193326Sed    OS << "Int: " << getInt();
243193326Sed    return;
244193326Sed  case Float:
245193326Sed    OS << "Float: " << GetApproxValue(getFloat());
246193326Sed    return;
247193326Sed  case Vector:
248234353Sdim    OS << "Vector: ";
249234353Sdim    getVectorElt(0).dump(OS);
250234353Sdim    for (unsigned i = 1; i != getVectorLength(); ++i) {
251234353Sdim      OS << ", ";
252234353Sdim      getVectorElt(i).dump(OS);
253234353Sdim    }
254193326Sed    return;
255193326Sed  case ComplexInt:
256193326Sed    OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
257193326Sed    return;
258193326Sed  case ComplexFloat:
259193326Sed    OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
260193326Sed       << ", " << GetApproxValue(getComplexFloatImag());
261234353Sdim    return;
262193326Sed  case LValue:
263193326Sed    OS << "LValue: <todo>";
264193326Sed    return;
265234353Sdim  case Array:
266234353Sdim    OS << "Array: ";
267234353Sdim    for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
268234353Sdim      getArrayInitializedElt(I).dump(OS);
269234353Sdim      if (I != getArraySize() - 1) OS << ", ";
270234353Sdim    }
271234353Sdim    if (hasArrayFiller()) {
272234353Sdim      OS << getArraySize() - getArrayInitializedElts() << " x ";
273234353Sdim      getArrayFiller().dump(OS);
274234353Sdim    }
275234353Sdim    return;
276234353Sdim  case Struct:
277234353Sdim    OS << "Struct ";
278234353Sdim    if (unsigned N = getStructNumBases()) {
279234353Sdim      OS << " bases: ";
280234353Sdim      getStructBase(0).dump(OS);
281234353Sdim      for (unsigned I = 1; I != N; ++I) {
282234353Sdim        OS << ", ";
283234353Sdim        getStructBase(I).dump(OS);
284234353Sdim      }
285234353Sdim    }
286234353Sdim    if (unsigned N = getStructNumFields()) {
287234353Sdim      OS << " fields: ";
288234353Sdim      getStructField(0).dump(OS);
289234353Sdim      for (unsigned I = 1; I != N; ++I) {
290234353Sdim        OS << ", ";
291234353Sdim        getStructField(I).dump(OS);
292234353Sdim      }
293234353Sdim    }
294234353Sdim    return;
295234353Sdim  case Union:
296234353Sdim    OS << "Union: ";
297234353Sdim    getUnionValue().dump(OS);
298234353Sdim    return;
299234353Sdim  case MemberPointer:
300234353Sdim    OS << "MemberPointer: <todo>";
301234353Sdim    return;
302234353Sdim  case AddrLabelDiff:
303234353Sdim    OS << "AddrLabelDiff: <todo>";
304234353Sdim    return;
305193326Sed  }
306234353Sdim  llvm_unreachable("Unknown APValue kind!");
307193326Sed}
308193326Sed
309234353Sdimvoid APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{
310234353Sdim  switch (getKind()) {
311226633Sdim  case APValue::Uninitialized:
312234353Sdim    Out << "<uninitialized>";
313234353Sdim    return;
314226633Sdim  case APValue::Int:
315234353Sdim    if (Ty->isBooleanType())
316234353Sdim      Out << (getInt().getBoolValue() ? "true" : "false");
317234353Sdim    else
318234353Sdim      Out << getInt();
319234353Sdim    return;
320226633Sdim  case APValue::Float:
321234353Sdim    Out << GetApproxValue(getFloat());
322234353Sdim    return;
323234353Sdim  case APValue::Vector: {
324234353Sdim    Out << '{';
325234353Sdim    QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
326234353Sdim    getVectorElt(0).printPretty(Out, Ctx, ElemTy);
327234353Sdim    for (unsigned i = 1; i != getVectorLength(); ++i) {
328226633Sdim      Out << ", ";
329234353Sdim      getVectorElt(i).printPretty(Out, Ctx, ElemTy);
330226633Sdim    }
331234353Sdim    Out << '}';
332234353Sdim    return;
333234353Sdim  }
334226633Sdim  case APValue::ComplexInt:
335234353Sdim    Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";
336234353Sdim    return;
337226633Sdim  case APValue::ComplexFloat:
338234353Sdim    Out << GetApproxValue(getComplexFloatReal()) << "+"
339234353Sdim        << GetApproxValue(getComplexFloatImag()) << "i";
340234353Sdim    return;
341234353Sdim  case APValue::LValue: {
342234353Sdim    LValueBase Base = getLValueBase();
343234353Sdim    if (!Base) {
344234353Sdim      Out << "0";
345234353Sdim      return;
346234353Sdim    }
347234353Sdim
348234353Sdim    bool IsReference = Ty->isReferenceType();
349234353Sdim    QualType InnerTy
350234353Sdim      = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();
351234353Sdim
352234353Sdim    if (!hasLValuePath()) {
353234353Sdim      // No lvalue path: just print the offset.
354234353Sdim      CharUnits O = getLValueOffset();
355234353Sdim      CharUnits S = Ctx.getTypeSizeInChars(InnerTy);
356234353Sdim      if (!O.isZero()) {
357234353Sdim        if (IsReference)
358234353Sdim          Out << "*(";
359234353Sdim        if (O % S) {
360234353Sdim          Out << "(char*)";
361234353Sdim          S = CharUnits::One();
362234353Sdim        }
363234353Sdim        Out << '&';
364234353Sdim      } else if (!IsReference)
365234353Sdim        Out << '&';
366234353Sdim
367234353Sdim      if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
368234353Sdim        Out << *VD;
369234353Sdim      else
370234353Sdim        Base.get<const Expr*>()->printPretty(Out, Ctx, 0,
371234353Sdim                                             Ctx.getPrintingPolicy());
372234353Sdim      if (!O.isZero()) {
373234353Sdim        Out << " + " << (O / S);
374234353Sdim        if (IsReference)
375234353Sdim          Out << ')';
376234353Sdim      }
377234353Sdim      return;
378234353Sdim    }
379234353Sdim
380234353Sdim    // We have an lvalue path. Print it out nicely.
381234353Sdim    if (!IsReference)
382234353Sdim      Out << '&';
383234353Sdim    else if (isLValueOnePastTheEnd())
384234353Sdim      Out << "*(&";
385234353Sdim
386234353Sdim    QualType ElemTy;
387234353Sdim    if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
388234353Sdim      Out << *VD;
389234353Sdim      ElemTy = VD->getType();
390234353Sdim    } else {
391234353Sdim      const Expr *E = Base.get<const Expr*>();
392234353Sdim      E->printPretty(Out, Ctx, 0,Ctx.getPrintingPolicy());
393234353Sdim      ElemTy = E->getType();
394234353Sdim    }
395234353Sdim
396234353Sdim    ArrayRef<LValuePathEntry> Path = getLValuePath();
397234353Sdim    const CXXRecordDecl *CastToBase = 0;
398234353Sdim    for (unsigned I = 0, N = Path.size(); I != N; ++I) {
399234353Sdim      if (ElemTy->getAs<RecordType>()) {
400234353Sdim        // The lvalue refers to a class type, so the next path entry is a base
401234353Sdim        // or member.
402234353Sdim        const Decl *BaseOrMember =
403234353Sdim        BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer();
404234353Sdim        if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
405234353Sdim          CastToBase = RD;
406234353Sdim          ElemTy = Ctx.getRecordType(RD);
407234353Sdim        } else {
408234353Sdim          const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
409234353Sdim          Out << ".";
410234353Sdim          if (CastToBase)
411234353Sdim            Out << *CastToBase << "::";
412234353Sdim          Out << *VD;
413234353Sdim          ElemTy = VD->getType();
414234353Sdim        }
415234353Sdim      } else {
416234353Sdim        // The lvalue must refer to an array.
417234353Sdim        Out << '[' << Path[I].ArrayIndex << ']';
418234353Sdim        ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType();
419234353Sdim      }
420234353Sdim    }
421234353Sdim
422234353Sdim    // Handle formatting of one-past-the-end lvalues.
423234353Sdim    if (isLValueOnePastTheEnd()) {
424234353Sdim      // FIXME: If CastToBase is non-0, we should prefix the output with
425234353Sdim      // "(CastToBase*)".
426234353Sdim      Out << " + 1";
427234353Sdim      if (IsReference)
428234353Sdim        Out << ')';
429234353Sdim    }
430234353Sdim    return;
431226633Sdim  }
432234353Sdim  case APValue::Array: {
433234353Sdim    const ArrayType *AT = Ctx.getAsArrayType(Ty);
434234353Sdim    QualType ElemTy = AT->getElementType();
435234353Sdim    Out << '{';
436234353Sdim    if (unsigned N = getArrayInitializedElts()) {
437234353Sdim      getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy);
438234353Sdim      for (unsigned I = 1; I != N; ++I) {
439234353Sdim        Out << ", ";
440234353Sdim        if (I == 10) {
441234353Sdim          // Avoid printing out the entire contents of large arrays.
442234353Sdim          Out << "...";
443234353Sdim          break;
444234353Sdim        }
445234353Sdim        getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy);
446234353Sdim      }
447234353Sdim    }
448234353Sdim    Out << '}';
449234353Sdim    return;
450234353Sdim  }
451234353Sdim  case APValue::Struct: {
452234353Sdim    Out << '{';
453234353Sdim    const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
454234353Sdim    bool First = true;
455234353Sdim    if (unsigned N = getStructNumBases()) {
456234353Sdim      const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
457234353Sdim      CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
458234353Sdim      for (unsigned I = 0; I != N; ++I, ++BI) {
459234353Sdim        assert(BI != CD->bases_end());
460234353Sdim        if (!First)
461234353Sdim          Out << ", ";
462234353Sdim        getStructBase(I).printPretty(Out, Ctx, BI->getType());
463234353Sdim        First = false;
464234353Sdim      }
465234353Sdim    }
466234353Sdim    for (RecordDecl::field_iterator FI = RD->field_begin();
467234353Sdim         FI != RD->field_end(); ++FI) {
468234353Sdim      if (!First)
469234353Sdim        Out << ", ";
470234353Sdim      if ((*FI)->isUnnamedBitfield()) continue;
471234353Sdim      getStructField((*FI)->getFieldIndex()).
472234353Sdim        printPretty(Out, Ctx, (*FI)->getType());
473234353Sdim      First = false;
474234353Sdim    }
475234353Sdim    Out << '}';
476234353Sdim    return;
477234353Sdim  }
478234353Sdim  case APValue::Union:
479234353Sdim    Out << '{';
480234353Sdim    if (const FieldDecl *FD = getUnionField()) {
481234353Sdim      Out << "." << *FD << " = ";
482234353Sdim      getUnionValue().printPretty(Out, Ctx, FD->getType());
483234353Sdim    }
484234353Sdim    Out << '}';
485234353Sdim    return;
486234353Sdim  case APValue::MemberPointer:
487234353Sdim    // FIXME: This is not enough to unambiguously identify the member in a
488234353Sdim    // multiple-inheritance scenario.
489234353Sdim    if (const ValueDecl *VD = getMemberPointerDecl()) {
490234353Sdim      Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;
491234353Sdim      return;
492234353Sdim    }
493234353Sdim    Out << "0";
494234353Sdim    return;
495234353Sdim  case APValue::AddrLabelDiff:
496234353Sdim    Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName();
497234353Sdim    Out << " - ";
498234353Sdim    Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName();
499234353Sdim    return;
500234353Sdim  }
501234353Sdim  llvm_unreachable("Unknown APValue kind!");
502226633Sdim}
503226633Sdim
504234353Sdimstd::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const {
505234353Sdim  std::string Result;
506234353Sdim  llvm::raw_string_ostream Out(Result);
507234353Sdim  printPretty(Out, Ctx, Ty);
508234353Sdim  Out.flush();
509234353Sdim  return Result;
510226633Sdim}
511226633Sdim
512234353Sdimconst APValue::LValueBase APValue::getLValueBase() const {
513202379Srdivacky  assert(isLValue() && "Invalid accessor");
514234353Sdim  return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getPointer();
515202379Srdivacky}
516202379Srdivacky
517234353Sdimbool APValue::isLValueOnePastTheEnd() const {
518234353Sdim  assert(isLValue() && "Invalid accessor");
519234353Sdim  return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getInt();
520202379Srdivacky}
521202379Srdivacky
522234353SdimCharUnits &APValue::getLValueOffset() {
523202379Srdivacky  assert(isLValue() && "Invalid accessor");
524234353Sdim  return ((LV*)(void*)Data)->Offset;
525202379Srdivacky}
526202379Srdivacky
527234353Sdimbool APValue::hasLValuePath() const {
528234353Sdim  assert(isLValue() && "Invalid accessor");
529234353Sdim  return ((const LV*)(const char*)Data)->hasPath();
530234353Sdim}
531234353Sdim
532234353SdimArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
533234353Sdim  assert(isLValue() && hasLValuePath() && "Invalid accessor");
534234353Sdim  const LV &LVal = *((const LV*)(const char*)Data);
535234353Sdim  return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
536234353Sdim}
537234353Sdim
538234353Sdimunsigned APValue::getLValueCallIndex() const {
539234353Sdim  assert(isLValue() && "Invalid accessor");
540234353Sdim  return ((const LV*)(const char*)Data)->CallIndex;
541234353Sdim}
542234353Sdim
543234353Sdimvoid APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
544234353Sdim                        unsigned CallIndex) {
545234353Sdim  assert(isLValue() && "Invalid accessor");
546234353Sdim  LV &LVal = *((LV*)(char*)Data);
547234353Sdim  LVal.BaseAndIsOnePastTheEnd.setPointer(B);
548234353Sdim  LVal.BaseAndIsOnePastTheEnd.setInt(false);
549234353Sdim  LVal.Offset = O;
550234353Sdim  LVal.CallIndex = CallIndex;
551234353Sdim  LVal.resizePath((unsigned)-1);
552234353Sdim}
553234353Sdim
554234353Sdimvoid APValue::setLValue(LValueBase B, const CharUnits &O,
555234353Sdim                        ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
556234353Sdim                        unsigned CallIndex) {
557234353Sdim  assert(isLValue() && "Invalid accessor");
558234353Sdim  LV &LVal = *((LV*)(char*)Data);
559234353Sdim  LVal.BaseAndIsOnePastTheEnd.setPointer(B);
560234353Sdim  LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd);
561234353Sdim  LVal.Offset = O;
562234353Sdim  LVal.CallIndex = CallIndex;
563234353Sdim  LVal.resizePath(Path.size());
564234353Sdim  memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
565234353Sdim}
566234353Sdim
567234353Sdimconst ValueDecl *APValue::getMemberPointerDecl() const {
568234353Sdim  assert(isMemberPointer() && "Invalid accessor");
569234353Sdim  const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
570234353Sdim  return MPD.MemberAndIsDerivedMember.getPointer();
571234353Sdim}
572234353Sdim
573234353Sdimbool APValue::isMemberPointerToDerivedMember() const {
574234353Sdim  assert(isMemberPointer() && "Invalid accessor");
575234353Sdim  const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
576234353Sdim  return MPD.MemberAndIsDerivedMember.getInt();
577234353Sdim}
578234353Sdim
579234353SdimArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {
580234353Sdim  assert(isMemberPointer() && "Invalid accessor");
581234353Sdim  const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
582234353Sdim  return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength);
583234353Sdim}
584234353Sdim
585202379Srdivackyvoid APValue::MakeLValue() {
586202379Srdivacky  assert(isUninit() && "Bad state change");
587234353Sdim  assert(sizeof(LV) <= MaxSize && "LV too big");
588202379Srdivacky  new ((void*)(char*)Data) LV();
589202379Srdivacky  Kind = LValue;
590202379Srdivacky}
591202379Srdivacky
592234353Sdimvoid APValue::MakeArray(unsigned InitElts, unsigned Size) {
593234353Sdim  assert(isUninit() && "Bad state change");
594234353Sdim  new ((void*)(char*)Data) Arr(InitElts, Size);
595234353Sdim  Kind = Array;
596234353Sdim}
597234353Sdim
598234353Sdimvoid APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
599234353Sdim                                ArrayRef<const CXXRecordDecl*> Path) {
600234353Sdim  assert(isUninit() && "Bad state change");
601234353Sdim  MemberPointerData *MPD = new ((void*)(char*)Data) MemberPointerData;
602234353Sdim  Kind = MemberPointer;
603234353Sdim  MPD->MemberAndIsDerivedMember.setPointer(Member);
604234353Sdim  MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
605234353Sdim  MPD->resizePath(Path.size());
606234353Sdim  memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));
607234353Sdim}
608