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