xref: /llvm-project/clang/lib/AST/APValue.cpp (revision 375f09f5bf2d63b9db3960f4723d8ee12fa3e25e)
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 "clang/Basic/Diagnostic.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include "llvm/Support/ErrorHandling.h"
24 using namespace clang;
25 
26 namespace {
27   struct LVBase {
28     llvm::PointerIntPair<APValue::LValueBase, 1, bool> BaseAndIsOnePastTheEnd;
29     CharUnits Offset;
30     unsigned PathLength;
31   };
32 }
33 
34 struct APValue::LV : LVBase {
35   static const unsigned InlinePathSpace =
36       (MaxSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
37 
38   /// Path - The sequence of base classes, fields and array indices to follow to
39   /// walk from Base to the subobject. When performing GCC-style folding, there
40   /// may not be such a path.
41   union {
42     LValuePathEntry Path[InlinePathSpace];
43     LValuePathEntry *PathPtr;
44   };
45 
46   LV() { PathLength = (unsigned)-1; }
47   ~LV() { resizePath(0); }
48 
49   void resizePath(unsigned Length) {
50     if (Length == PathLength)
51       return;
52     if (hasPathPtr())
53       delete [] PathPtr;
54     PathLength = Length;
55     if (hasPathPtr())
56       PathPtr = new LValuePathEntry[Length];
57   }
58 
59   bool hasPath() const { return PathLength != (unsigned)-1; }
60   bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }
61 
62   LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }
63   const LValuePathEntry *getPath() const {
64     return hasPathPtr() ? PathPtr : Path;
65   }
66 };
67 
68 namespace {
69   struct MemberPointerBase {
70     llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember;
71     unsigned PathLength;
72   };
73 }
74 
75 struct APValue::MemberPointerData : MemberPointerBase {
76   static const unsigned InlinePathSpace =
77       (MaxSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*);
78   typedef const CXXRecordDecl *PathElem;
79   union {
80     PathElem Path[InlinePathSpace];
81     PathElem *PathPtr;
82   };
83 
84   MemberPointerData() { PathLength = 0; }
85   ~MemberPointerData() { resizePath(0); }
86 
87   void resizePath(unsigned Length) {
88     if (Length == PathLength)
89       return;
90     if (hasPathPtr())
91       delete [] PathPtr;
92     PathLength = Length;
93     if (hasPathPtr())
94       PathPtr = new PathElem[Length];
95   }
96 
97   bool hasPathPtr() const { return PathLength > InlinePathSpace; }
98 
99   PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; }
100   const PathElem *getPath() const {
101     return hasPathPtr() ? PathPtr : Path;
102   }
103 };
104 
105 // FIXME: Reduce the malloc traffic here.
106 
107 APValue::Arr::Arr(unsigned NumElts, unsigned Size) :
108   Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]),
109   NumElts(NumElts), ArrSize(Size) {}
110 APValue::Arr::~Arr() { delete [] Elts; }
111 
112 APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) :
113   Elts(new APValue[NumBases+NumFields]),
114   NumBases(NumBases), NumFields(NumFields) {}
115 APValue::StructData::~StructData() {
116   delete [] Elts;
117 }
118 
119 APValue::UnionData::UnionData() : Field(0), Value(new APValue) {}
120 APValue::UnionData::~UnionData () {
121   delete Value;
122 }
123 
124 const APValue &APValue::operator=(const APValue &RHS) {
125   if (this == &RHS)
126     return *this;
127   if (Kind != RHS.Kind || Kind == Array || Kind == Struct ||
128       Kind == MemberPointer) {
129     MakeUninit();
130     if (RHS.isInt())
131       MakeInt();
132     else if (RHS.isFloat())
133       MakeFloat();
134     else if (RHS.isVector())
135       MakeVector();
136     else if (RHS.isComplexInt())
137       MakeComplexInt();
138     else if (RHS.isComplexFloat())
139       MakeComplexFloat();
140     else if (RHS.isLValue())
141       MakeLValue();
142     else if (RHS.isArray())
143       MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
144     else if (RHS.isStruct())
145       MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());
146     else if (RHS.isUnion())
147       MakeUnion();
148     else if (RHS.isMemberPointer())
149       MakeMemberPointer(RHS.getMemberPointerDecl(),
150                         RHS.isMemberPointerToDerivedMember(),
151                         RHS.getMemberPointerPath());
152   }
153   if (isInt())
154     setInt(RHS.getInt());
155   else if (isFloat())
156     setFloat(RHS.getFloat());
157   else if (isVector())
158     setVector(((const Vec *)(const char *)RHS.Data)->Elts,
159               RHS.getVectorLength());
160   else if (isComplexInt())
161     setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
162   else if (isComplexFloat())
163     setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
164   else if (isLValue()) {
165     if (RHS.hasLValuePath())
166       setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
167                 RHS.isLValueOnePastTheEnd());
168     else
169       setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath());
170   } else if (isArray()) {
171     for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)
172       getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);
173     if (RHS.hasArrayFiller())
174       getArrayFiller() = RHS.getArrayFiller();
175   } else if (isStruct()) {
176     for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I)
177       getStructBase(I) = RHS.getStructBase(I);
178     for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I)
179       getStructField(I) = RHS.getStructField(I);
180   } else if (isUnion())
181     setUnion(RHS.getUnionField(), RHS.getUnionValue());
182   return *this;
183 }
184 
185 void APValue::MakeUninit() {
186   if (Kind == Int)
187     ((APSInt*)(char*)Data)->~APSInt();
188   else if (Kind == Float)
189     ((APFloat*)(char*)Data)->~APFloat();
190   else if (Kind == Vector)
191     ((Vec*)(char*)Data)->~Vec();
192   else if (Kind == ComplexInt)
193     ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
194   else if (Kind == ComplexFloat)
195     ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
196   else if (Kind == LValue)
197     ((LV*)(char*)Data)->~LV();
198   else if (Kind == Array)
199     ((Arr*)(char*)Data)->~Arr();
200   else if (Kind == Struct)
201     ((StructData*)(char*)Data)->~StructData();
202   else if (Kind == Union)
203     ((UnionData*)(char*)Data)->~UnionData();
204   else if (Kind == MemberPointer)
205     ((MemberPointerData*)(char*)Data)->~MemberPointerData();
206   Kind = Uninitialized;
207 }
208 
209 void APValue::dump() const {
210   dump(llvm::errs());
211   llvm::errs() << '\n';
212 }
213 
214 static double GetApproxValue(const llvm::APFloat &F) {
215   llvm::APFloat V = F;
216   bool ignored;
217   V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
218             &ignored);
219   return V.convertToDouble();
220 }
221 
222 void APValue::dump(raw_ostream &OS) const {
223   switch (getKind()) {
224   case Uninitialized:
225     OS << "Uninitialized";
226     return;
227   case Int:
228     OS << "Int: " << getInt();
229     return;
230   case Float:
231     OS << "Float: " << GetApproxValue(getFloat());
232     return;
233   case Vector:
234     OS << "Vector: ";
235     getVectorElt(0).dump(OS);
236     for (unsigned i = 1; i != getVectorLength(); ++i) {
237       OS << ", ";
238       getVectorElt(i).dump(OS);
239     }
240     return;
241   case ComplexInt:
242     OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
243     return;
244   case ComplexFloat:
245     OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
246        << ", " << GetApproxValue(getComplexFloatImag());
247     return;
248   case LValue:
249     OS << "LValue: <todo>";
250     return;
251   case Array:
252     OS << "Array: ";
253     for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
254       getArrayInitializedElt(I).dump(OS);
255       if (I != getArraySize() - 1) OS << ", ";
256     }
257     if (hasArrayFiller()) {
258       OS << getArraySize() - getArrayInitializedElts() << " x ";
259       getArrayFiller().dump(OS);
260     }
261     return;
262   case Struct:
263     OS << "Struct ";
264     if (unsigned N = getStructNumBases()) {
265       OS << " bases: ";
266       getStructBase(0).dump(OS);
267       for (unsigned I = 1; I != N; ++I) {
268         OS << ", ";
269         getStructBase(I).dump(OS);
270       }
271     }
272     if (unsigned N = getStructNumFields()) {
273       OS << " fields: ";
274       getStructField(0).dump(OS);
275       for (unsigned I = 1; I != N; ++I) {
276         OS << ", ";
277         getStructField(I).dump(OS);
278       }
279     }
280     return;
281   case Union:
282     OS << "Union: ";
283     getUnionValue().dump(OS);
284     return;
285   case MemberPointer:
286     OS << "MemberPointer: <todo>";
287     return;
288   }
289   llvm_unreachable("Unknown APValue kind!");
290 }
291 
292 void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{
293   switch (getKind()) {
294   case APValue::Uninitialized:
295     Out << "<uninitialized>";
296     return;
297   case APValue::Int:
298     Out << getInt();
299     return;
300   case APValue::Float:
301     Out << GetApproxValue(getFloat());
302     return;
303   case APValue::Vector: {
304     Out << '{';
305     QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
306     getVectorElt(0).printPretty(Out, Ctx, ElemTy);
307     for (unsigned i = 1; i != getVectorLength(); ++i) {
308       Out << ", ";
309       getVectorElt(i).printPretty(Out, Ctx, ElemTy);
310     }
311     Out << '}';
312     return;
313   }
314   case APValue::ComplexInt:
315     Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";
316     return;
317   case APValue::ComplexFloat:
318     Out << GetApproxValue(getComplexFloatReal()) << "+"
319         << GetApproxValue(getComplexFloatImag()) << "i";
320     return;
321   case APValue::LValue: {
322     LValueBase Base = getLValueBase();
323     if (!Base) {
324       Out << "0";
325       return;
326     }
327 
328     bool IsReference = Ty->isReferenceType();
329     QualType InnerTy
330       = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();
331 
332     if (!hasLValuePath()) {
333       // No lvalue path: just print the offset.
334       CharUnits O = getLValueOffset();
335       CharUnits S = Ctx.getTypeSizeInChars(InnerTy);
336       if (!O.isZero()) {
337         if (IsReference)
338           Out << "*(";
339         if (O % S) {
340           Out << "(char*)";
341           S = CharUnits::One();
342         }
343         Out << '&';
344       } else if (!IsReference)
345         Out << '&';
346 
347       if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
348         Out << *VD;
349       else
350         Base.get<const Expr*>()->printPretty(Out, Ctx, 0,
351                                              Ctx.getPrintingPolicy());
352       if (!O.isZero()) {
353         Out << " + " << (O / S);
354         if (IsReference)
355           Out << ')';
356       }
357       return;
358     }
359 
360     // We have an lvalue path. Print it out nicely.
361     if (!IsReference)
362       Out << '&';
363     else if (isLValueOnePastTheEnd())
364       Out << "*(&";
365 
366     QualType ElemTy;
367     if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
368       Out << *VD;
369       ElemTy = VD->getType();
370     } else {
371       const Expr *E = Base.get<const Expr*>();
372       E->printPretty(Out, Ctx, 0,Ctx.getPrintingPolicy());
373       ElemTy = E->getType();
374     }
375 
376     ArrayRef<LValuePathEntry> Path = getLValuePath();
377     const CXXRecordDecl *CastToBase = 0;
378     for (unsigned I = 0, N = Path.size(); I != N; ++I) {
379       if (ElemTy->getAs<RecordType>()) {
380         // The lvalue refers to a class type, so the next path entry is a base
381         // or member.
382         const Decl *BaseOrMember =
383         BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer();
384         if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
385           CastToBase = RD;
386           ElemTy = Ctx.getRecordType(RD);
387         } else {
388           const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
389           Out << ".";
390           if (CastToBase)
391             Out << *CastToBase << "::";
392           Out << *VD;
393           ElemTy = VD->getType();
394         }
395       } else {
396         // The lvalue must refer to an array.
397         Out << '[' << Path[I].ArrayIndex << ']';
398         ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType();
399       }
400     }
401 
402     // Handle formatting of one-past-the-end lvalues.
403     if (isLValueOnePastTheEnd()) {
404       // FIXME: If CastToBase is non-0, we should prefix the output with
405       // "(CastToBase*)".
406       Out << " + 1";
407       if (IsReference)
408         Out << ')';
409     }
410     return;
411   }
412   case APValue::Array: {
413     const ArrayType *AT = Ctx.getAsArrayType(Ty);
414     QualType ElemTy = AT->getElementType();
415     Out << '{';
416     if (unsigned N = getArrayInitializedElts()) {
417       getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy);
418       for (unsigned I = 1; I != N; ++I) {
419         Out << ", ";
420         if (I == 10) {
421           // Avoid printing out the entire contents of large arrays.
422           Out << "...";
423           break;
424         }
425         getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy);
426       }
427     }
428     Out << '}';
429     return;
430   }
431   case APValue::Struct: {
432     Out << '{';
433     const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
434     bool First = true;
435     if (unsigned N = getStructNumBases()) {
436       const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
437       CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
438       for (unsigned I = 0; I != N; ++I, ++BI) {
439         assert(BI != CD->bases_end());
440         if (!First)
441           Out << ", ";
442         getStructBase(I).printPretty(Out, Ctx, BI->getType());
443         First = false;
444       }
445     }
446     for (RecordDecl::field_iterator FI = RD->field_begin();
447          FI != RD->field_end(); ++FI) {
448       if (!First)
449         Out << ", ";
450       if ((*FI)->isUnnamedBitfield()) continue;
451       getStructField((*FI)->getFieldIndex()).
452         printPretty(Out, Ctx, (*FI)->getType());
453       First = false;
454     }
455     Out << '}';
456     return;
457   }
458   case APValue::Union:
459     Out << '{';
460     if (const FieldDecl *FD = getUnionField()) {
461       Out << "." << *FD << " = ";
462       getUnionValue().printPretty(Out, Ctx, FD->getType());
463     }
464     Out << '}';
465     return;
466   case APValue::MemberPointer:
467     // FIXME: This is not enough to unambiguously identify the member in a
468     // multiple-inheritance scenario.
469     if (const ValueDecl *VD = getMemberPointerDecl()) {
470       Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;
471       return;
472     }
473     Out << "0";
474     return;
475   }
476   llvm_unreachable("Unknown APValue kind!");
477 }
478 
479 std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const {
480   std::string Result;
481   llvm::raw_string_ostream Out(Result);
482   printPretty(Out, Ctx, Ty);
483   Out.flush();
484   return Result;
485 }
486 
487 const APValue::LValueBase APValue::getLValueBase() const {
488   assert(isLValue() && "Invalid accessor");
489   return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getPointer();
490 }
491 
492 bool APValue::isLValueOnePastTheEnd() const {
493   assert(isLValue() && "Invalid accessor");
494   return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getInt();
495 }
496 
497 CharUnits &APValue::getLValueOffset() {
498   assert(isLValue() && "Invalid accessor");
499   return ((LV*)(void*)Data)->Offset;
500 }
501 
502 bool APValue::hasLValuePath() const {
503   assert(isLValue() && "Invalid accessor");
504   return ((const LV*)(const char*)Data)->hasPath();
505 }
506 
507 ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
508   assert(isLValue() && hasLValuePath() && "Invalid accessor");
509   const LV &LVal = *((const LV*)(const char*)Data);
510   return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
511 }
512 
513 void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath) {
514   assert(isLValue() && "Invalid accessor");
515   LV &LVal = *((LV*)(char*)Data);
516   LVal.BaseAndIsOnePastTheEnd.setPointer(B);
517   LVal.BaseAndIsOnePastTheEnd.setInt(false);
518   LVal.Offset = O;
519   LVal.resizePath((unsigned)-1);
520 }
521 
522 void APValue::setLValue(LValueBase B, const CharUnits &O,
523                         ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd) {
524   assert(isLValue() && "Invalid accessor");
525   LV &LVal = *((LV*)(char*)Data);
526   LVal.BaseAndIsOnePastTheEnd.setPointer(B);
527   LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd);
528   LVal.Offset = O;
529   LVal.resizePath(Path.size());
530   memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
531 }
532 
533 const ValueDecl *APValue::getMemberPointerDecl() const {
534   assert(isMemberPointer() && "Invalid accessor");
535   const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
536   return MPD.MemberAndIsDerivedMember.getPointer();
537 }
538 
539 bool APValue::isMemberPointerToDerivedMember() const {
540   assert(isMemberPointer() && "Invalid accessor");
541   const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
542   return MPD.MemberAndIsDerivedMember.getInt();
543 }
544 
545 ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {
546   assert(isMemberPointer() && "Invalid accessor");
547   const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
548   return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength);
549 }
550 
551 void APValue::MakeLValue() {
552   assert(isUninit() && "Bad state change");
553   assert(sizeof(LV) <= MaxSize && "LV too big");
554   new ((void*)(char*)Data) LV();
555   Kind = LValue;
556 }
557 
558 void APValue::MakeArray(unsigned InitElts, unsigned Size) {
559   assert(isUninit() && "Bad state change");
560   new ((void*)(char*)Data) Arr(InitElts, Size);
561   Kind = Array;
562 }
563 
564 void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
565                                 ArrayRef<const CXXRecordDecl*> Path) {
566   assert(isUninit() && "Bad state change");
567   MemberPointerData *MPD = new ((void*)(char*)Data) MemberPointerData;
568   Kind = MemberPointer;
569   MPD->MemberAndIsDerivedMember.setPointer(Member);
570   MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
571   MPD->resizePath(Path.size());
572   memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));
573 }
574