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