Clang Project

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