1 //===--- APValue.cpp - Union class for APFloat/APSInt/Complex -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the APValue class.
12 //===----------------------------------------------------------------------===//
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/ErrorHandling.h"
23 #include "llvm/Support/raw_ostream.h"
24 using namespace clang
;
28 llvm::PointerIntPair
<APValue::LValueBase
, 1, bool> BaseAndIsOnePastTheEnd
;
35 struct APValue::LV
: LVBase
{
36 static const unsigned InlinePathSpace
=
37 (DataSize
- sizeof(LVBase
)) / sizeof(LValuePathEntry
);
39 /// Path - The sequence of base classes, fields and array indices to follow to
40 /// walk from Base to the subobject. When performing GCC-style folding, there
41 /// may not be such a path.
43 LValuePathEntry Path
[InlinePathSpace
];
44 LValuePathEntry
*PathPtr
;
47 LV() { PathLength
= (unsigned)-1; }
48 ~LV() { resizePath(0); }
50 void resizePath(unsigned Length
) {
51 if (Length
== PathLength
)
57 PathPtr
= new LValuePathEntry
[Length
];
60 bool hasPath() const { return PathLength
!= (unsigned)-1; }
61 bool hasPathPtr() const { return hasPath() && PathLength
> InlinePathSpace
; }
63 LValuePathEntry
*getPath() { return hasPathPtr() ? PathPtr
: Path
; }
64 const LValuePathEntry
*getPath() const {
65 return hasPathPtr() ? PathPtr
: Path
;
70 struct MemberPointerBase
{
71 llvm::PointerIntPair
<const ValueDecl
*, 1, bool> MemberAndIsDerivedMember
;
76 struct APValue::MemberPointerData
: MemberPointerBase
{
77 static const unsigned InlinePathSpace
=
78 (DataSize
- sizeof(MemberPointerBase
)) / sizeof(const CXXRecordDecl
*);
79 typedef const CXXRecordDecl
*PathElem
;
81 PathElem Path
[InlinePathSpace
];
85 MemberPointerData() { PathLength
= 0; }
86 ~MemberPointerData() { resizePath(0); }
88 void resizePath(unsigned Length
) {
89 if (Length
== PathLength
)
95 PathPtr
= new PathElem
[Length
];
98 bool hasPathPtr() const { return PathLength
> InlinePathSpace
; }
100 PathElem
*getPath() { return hasPathPtr() ? PathPtr
: Path
; }
101 const PathElem
*getPath() const {
102 return hasPathPtr() ? PathPtr
: Path
;
106 // FIXME: Reduce the malloc traffic here.
108 APValue::Arr::Arr(unsigned NumElts
, unsigned Size
) :
109 Elts(new APValue
[NumElts
+ (NumElts
!= Size
? 1 : 0)]),
110 NumElts(NumElts
), ArrSize(Size
) {}
111 APValue::Arr::~Arr() { delete [] Elts
; }
113 APValue::StructData::StructData(unsigned NumBases
, unsigned NumFields
) :
114 Elts(new APValue
[NumBases
+NumFields
]),
115 NumBases(NumBases
), NumFields(NumFields
) {}
116 APValue::StructData::~StructData() {
120 APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue
) {}
121 APValue::UnionData::~UnionData () {
125 APValue::APValue(const APValue
&RHS
) : Kind(Uninitialized
) {
126 switch (RHS
.getKind()) {
131 setInt(RHS
.getInt());
135 setFloat(RHS
.getFloat());
139 setVector(((const Vec
*)(const char *)RHS
.Data
.buffer
)->Elts
,
140 RHS
.getVectorLength());
144 setComplexInt(RHS
.getComplexIntReal(), RHS
.getComplexIntImag());
148 setComplexFloat(RHS
.getComplexFloatReal(), RHS
.getComplexFloatImag());
152 if (RHS
.hasLValuePath())
153 setLValue(RHS
.getLValueBase(), RHS
.getLValueOffset(), RHS
.getLValuePath(),
154 RHS
.isLValueOnePastTheEnd(), RHS
.getLValueCallIndex());
156 setLValue(RHS
.getLValueBase(), RHS
.getLValueOffset(), NoLValuePath(),
157 RHS
.getLValueCallIndex());
160 MakeArray(RHS
.getArrayInitializedElts(), RHS
.getArraySize());
161 for (unsigned I
= 0, N
= RHS
.getArrayInitializedElts(); I
!= N
; ++I
)
162 getArrayInitializedElt(I
) = RHS
.getArrayInitializedElt(I
);
163 if (RHS
.hasArrayFiller())
164 getArrayFiller() = RHS
.getArrayFiller();
167 MakeStruct(RHS
.getStructNumBases(), RHS
.getStructNumFields());
168 for (unsigned I
= 0, N
= RHS
.getStructNumBases(); I
!= N
; ++I
)
169 getStructBase(I
) = RHS
.getStructBase(I
);
170 for (unsigned I
= 0, N
= RHS
.getStructNumFields(); I
!= N
; ++I
)
171 getStructField(I
) = RHS
.getStructField(I
);
175 setUnion(RHS
.getUnionField(), RHS
.getUnionValue());
178 MakeMemberPointer(RHS
.getMemberPointerDecl(),
179 RHS
.isMemberPointerToDerivedMember(),
180 RHS
.getMemberPointerPath());
184 setAddrLabelDiff(RHS
.getAddrLabelDiffLHS(), RHS
.getAddrLabelDiffRHS());
189 void APValue::DestroyDataAndMakeUninit() {
191 ((APSInt
*)(char*)Data
.buffer
)->~APSInt();
192 else if (Kind
== Float
)
193 ((APFloat
*)(char*)Data
.buffer
)->~APFloat();
194 else if (Kind
== Vector
)
195 ((Vec
*)(char*)Data
.buffer
)->~Vec();
196 else if (Kind
== ComplexInt
)
197 ((ComplexAPSInt
*)(char*)Data
.buffer
)->~ComplexAPSInt();
198 else if (Kind
== ComplexFloat
)
199 ((ComplexAPFloat
*)(char*)Data
.buffer
)->~ComplexAPFloat();
200 else if (Kind
== LValue
)
201 ((LV
*)(char*)Data
.buffer
)->~LV();
202 else if (Kind
== Array
)
203 ((Arr
*)(char*)Data
.buffer
)->~Arr();
204 else if (Kind
== Struct
)
205 ((StructData
*)(char*)Data
.buffer
)->~StructData();
206 else if (Kind
== Union
)
207 ((UnionData
*)(char*)Data
.buffer
)->~UnionData();
208 else if (Kind
== MemberPointer
)
209 ((MemberPointerData
*)(char*)Data
.buffer
)->~MemberPointerData();
210 else if (Kind
== AddrLabelDiff
)
211 ((AddrLabelDiffData
*)(char*)Data
.buffer
)->~AddrLabelDiffData();
212 Kind
= Uninitialized
;
215 bool APValue::needsCleanup() const {
226 return getInt().needsCleanup();
228 return getFloat().needsCleanup();
230 assert(getComplexFloatImag().needsCleanup() ==
231 getComplexFloatReal().needsCleanup() &&
232 "In _Complex float types, real and imaginary values always have the "
234 return getComplexFloatReal().needsCleanup();
236 assert(getComplexIntImag().needsCleanup() ==
237 getComplexIntReal().needsCleanup() &&
238 "In _Complex int types, real and imaginary values must have the "
240 return getComplexIntReal().needsCleanup();
242 return reinterpret_cast<const LV
*>(Data
.buffer
)->hasPathPtr();
244 return reinterpret_cast<const MemberPointerData
*>(Data
.buffer
)
247 llvm_unreachable("Unknown APValue kind!");
250 void APValue::swap(APValue
&RHS
) {
251 std::swap(Kind
, RHS
.Kind
);
252 char TmpData
[DataSize
];
253 memcpy(TmpData
, Data
.buffer
, DataSize
);
254 memcpy(Data
.buffer
, RHS
.Data
.buffer
, DataSize
);
255 memcpy(RHS
.Data
.buffer
, TmpData
, DataSize
);
258 void APValue::dump() const {
260 llvm::errs() << '\n';
263 static double GetApproxValue(const llvm::APFloat
&F
) {
266 V
.convert(llvm::APFloat::IEEEdouble
, llvm::APFloat::rmNearestTiesToEven
,
268 return V
.convertToDouble();
271 void APValue::dump(raw_ostream
&OS
) const {
274 OS
<< "Uninitialized";
277 OS
<< "Int: " << getInt();
280 OS
<< "Float: " << GetApproxValue(getFloat());
284 getVectorElt(0).dump(OS
);
285 for (unsigned i
= 1; i
!= getVectorLength(); ++i
) {
287 getVectorElt(i
).dump(OS
);
291 OS
<< "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
294 OS
<< "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
295 << ", " << GetApproxValue(getComplexFloatImag());
298 OS
<< "LValue: <todo>";
302 for (unsigned I
= 0, N
= getArrayInitializedElts(); I
!= N
; ++I
) {
303 getArrayInitializedElt(I
).dump(OS
);
304 if (I
!= getArraySize() - 1) OS
<< ", ";
306 if (hasArrayFiller()) {
307 OS
<< getArraySize() - getArrayInitializedElts() << " x ";
308 getArrayFiller().dump(OS
);
313 if (unsigned N
= getStructNumBases()) {
315 getStructBase(0).dump(OS
);
316 for (unsigned I
= 1; I
!= N
; ++I
) {
318 getStructBase(I
).dump(OS
);
321 if (unsigned N
= getStructNumFields()) {
323 getStructField(0).dump(OS
);
324 for (unsigned I
= 1; I
!= N
; ++I
) {
326 getStructField(I
).dump(OS
);
332 getUnionValue().dump(OS
);
335 OS
<< "MemberPointer: <todo>";
338 OS
<< "AddrLabelDiff: <todo>";
341 llvm_unreachable("Unknown APValue kind!");
344 void APValue::printPretty(raw_ostream
&Out
, ASTContext
&Ctx
, QualType Ty
) const{
346 case APValue::Uninitialized
:
347 Out
<< "<uninitialized>";
350 if (Ty
->isBooleanType())
351 Out
<< (getInt().getBoolValue() ? "true" : "false");
356 Out
<< GetApproxValue(getFloat());
358 case APValue::Vector
: {
360 QualType ElemTy
= Ty
->getAs
<VectorType
>()->getElementType();
361 getVectorElt(0).printPretty(Out
, Ctx
, ElemTy
);
362 for (unsigned i
= 1; i
!= getVectorLength(); ++i
) {
364 getVectorElt(i
).printPretty(Out
, Ctx
, ElemTy
);
369 case APValue::ComplexInt
:
370 Out
<< getComplexIntReal() << "+" << getComplexIntImag() << "i";
372 case APValue::ComplexFloat
:
373 Out
<< GetApproxValue(getComplexFloatReal()) << "+"
374 << GetApproxValue(getComplexFloatImag()) << "i";
376 case APValue::LValue
: {
377 LValueBase Base
= getLValueBase();
383 bool IsReference
= Ty
->isReferenceType();
385 = IsReference
? Ty
.getNonReferenceType() : Ty
->getPointeeType();
386 if (InnerTy
.isNull())
389 if (!hasLValuePath()) {
390 // No lvalue path: just print the offset.
391 CharUnits O
= getLValueOffset();
392 CharUnits S
= Ctx
.getTypeSizeInChars(InnerTy
);
398 S
= CharUnits::One();
401 } else if (!IsReference
)
404 if (const ValueDecl
*VD
= Base
.dyn_cast
<const ValueDecl
*>())
407 assert(Base
.get
<const Expr
*>() != nullptr &&
408 "Expecting non-null Expr");
409 Base
.get
<const Expr
*>()->printPretty(Out
, nullptr,
410 Ctx
.getPrintingPolicy());
414 Out
<< " + " << (O
/ S
);
421 // We have an lvalue path. Print it out nicely.
424 else if (isLValueOnePastTheEnd())
428 if (const ValueDecl
*VD
= Base
.dyn_cast
<const ValueDecl
*>()) {
430 ElemTy
= VD
->getType();
432 const Expr
*E
= Base
.get
<const Expr
*>();
433 assert(E
!= nullptr && "Expecting non-null Expr");
434 E
->printPretty(Out
, nullptr, Ctx
.getPrintingPolicy());
435 ElemTy
= E
->getType();
438 ArrayRef
<LValuePathEntry
> Path
= getLValuePath();
439 const CXXRecordDecl
*CastToBase
= nullptr;
440 for (unsigned I
= 0, N
= Path
.size(); I
!= N
; ++I
) {
441 if (ElemTy
->getAs
<RecordType
>()) {
442 // The lvalue refers to a class type, so the next path entry is a base
444 const Decl
*BaseOrMember
=
445 BaseOrMemberType::getFromOpaqueValue(Path
[I
].BaseOrMember
).getPointer();
446 if (const CXXRecordDecl
*RD
= dyn_cast
<CXXRecordDecl
>(BaseOrMember
)) {
448 ElemTy
= Ctx
.getRecordType(RD
);
450 const ValueDecl
*VD
= cast
<ValueDecl
>(BaseOrMember
);
453 Out
<< *CastToBase
<< "::";
455 ElemTy
= VD
->getType();
458 // The lvalue must refer to an array.
459 Out
<< '[' << Path
[I
].ArrayIndex
<< ']';
460 ElemTy
= Ctx
.getAsArrayType(ElemTy
)->getElementType();
464 // Handle formatting of one-past-the-end lvalues.
465 if (isLValueOnePastTheEnd()) {
466 // FIXME: If CastToBase is non-0, we should prefix the output with
474 case APValue::Array
: {
475 const ArrayType
*AT
= Ctx
.getAsArrayType(Ty
);
476 QualType ElemTy
= AT
->getElementType();
478 if (unsigned N
= getArrayInitializedElts()) {
479 getArrayInitializedElt(0).printPretty(Out
, Ctx
, ElemTy
);
480 for (unsigned I
= 1; I
!= N
; ++I
) {
483 // Avoid printing out the entire contents of large arrays.
487 getArrayInitializedElt(I
).printPretty(Out
, Ctx
, ElemTy
);
493 case APValue::Struct
: {
495 const RecordDecl
*RD
= Ty
->getAs
<RecordType
>()->getDecl();
497 if (unsigned N
= getStructNumBases()) {
498 const CXXRecordDecl
*CD
= cast
<CXXRecordDecl
>(RD
);
499 CXXRecordDecl::base_class_const_iterator BI
= CD
->bases_begin();
500 for (unsigned I
= 0; I
!= N
; ++I
, ++BI
) {
501 assert(BI
!= CD
->bases_end());
504 getStructBase(I
).printPretty(Out
, Ctx
, BI
->getType());
508 for (const auto *FI
: RD
->fields()) {
511 if (FI
->isUnnamedBitfield()) continue;
512 getStructField(FI
->getFieldIndex()).
513 printPretty(Out
, Ctx
, FI
->getType());
521 if (const FieldDecl
*FD
= getUnionField()) {
522 Out
<< "." << *FD
<< " = ";
523 getUnionValue().printPretty(Out
, Ctx
, FD
->getType());
527 case APValue::MemberPointer
:
528 // FIXME: This is not enough to unambiguously identify the member in a
529 // multiple-inheritance scenario.
530 if (const ValueDecl
*VD
= getMemberPointerDecl()) {
531 Out
<< '&' << *cast
<CXXRecordDecl
>(VD
->getDeclContext()) << "::" << *VD
;
536 case APValue::AddrLabelDiff
:
537 Out
<< "&&" << getAddrLabelDiffLHS()->getLabel()->getName();
539 Out
<< "&&" << getAddrLabelDiffRHS()->getLabel()->getName();
542 llvm_unreachable("Unknown APValue kind!");
545 std::string
APValue::getAsString(ASTContext
&Ctx
, QualType Ty
) const {
547 llvm::raw_string_ostream
Out(Result
);
548 printPretty(Out
, Ctx
, Ty
);
553 const APValue::LValueBase
APValue::getLValueBase() const {
554 assert(isLValue() && "Invalid accessor");
555 return ((const LV
*)(const void*)Data
.buffer
)->BaseAndIsOnePastTheEnd
.getPointer();
558 bool APValue::isLValueOnePastTheEnd() const {
559 assert(isLValue() && "Invalid accessor");
560 return ((const LV
*)(const void*)Data
.buffer
)->BaseAndIsOnePastTheEnd
.getInt();
563 CharUnits
&APValue::getLValueOffset() {
564 assert(isLValue() && "Invalid accessor");
565 return ((LV
*)(void*)Data
.buffer
)->Offset
;
568 bool APValue::hasLValuePath() const {
569 assert(isLValue() && "Invalid accessor");
570 return ((const LV
*)(const char*)Data
.buffer
)->hasPath();
573 ArrayRef
<APValue::LValuePathEntry
> APValue::getLValuePath() const {
574 assert(isLValue() && hasLValuePath() && "Invalid accessor");
575 const LV
&LVal
= *((const LV
*)(const char*)Data
.buffer
);
576 return llvm::makeArrayRef(LVal
.getPath(), LVal
.PathLength
);
579 unsigned APValue::getLValueCallIndex() const {
580 assert(isLValue() && "Invalid accessor");
581 return ((const LV
*)(const char*)Data
.buffer
)->CallIndex
;
584 void APValue::setLValue(LValueBase B
, const CharUnits
&O
, NoLValuePath
,
585 unsigned CallIndex
) {
586 assert(isLValue() && "Invalid accessor");
587 LV
&LVal
= *((LV
*)(char*)Data
.buffer
);
588 LVal
.BaseAndIsOnePastTheEnd
.setPointer(B
);
589 LVal
.BaseAndIsOnePastTheEnd
.setInt(false);
591 LVal
.CallIndex
= CallIndex
;
592 LVal
.resizePath((unsigned)-1);
595 void APValue::setLValue(LValueBase B
, const CharUnits
&O
,
596 ArrayRef
<LValuePathEntry
> Path
, bool IsOnePastTheEnd
,
597 unsigned CallIndex
) {
598 assert(isLValue() && "Invalid accessor");
599 LV
&LVal
= *((LV
*)(char*)Data
.buffer
);
600 LVal
.BaseAndIsOnePastTheEnd
.setPointer(B
);
601 LVal
.BaseAndIsOnePastTheEnd
.setInt(IsOnePastTheEnd
);
603 LVal
.CallIndex
= CallIndex
;
604 LVal
.resizePath(Path
.size());
605 memcpy(LVal
.getPath(), Path
.data(), Path
.size() * sizeof(LValuePathEntry
));
608 const ValueDecl
*APValue::getMemberPointerDecl() const {
609 assert(isMemberPointer() && "Invalid accessor");
610 const MemberPointerData
&MPD
=
611 *((const MemberPointerData
*)(const char *)Data
.buffer
);
612 return MPD
.MemberAndIsDerivedMember
.getPointer();
615 bool APValue::isMemberPointerToDerivedMember() const {
616 assert(isMemberPointer() && "Invalid accessor");
617 const MemberPointerData
&MPD
=
618 *((const MemberPointerData
*)(const char *)Data
.buffer
);
619 return MPD
.MemberAndIsDerivedMember
.getInt();
622 ArrayRef
<const CXXRecordDecl
*> APValue::getMemberPointerPath() const {
623 assert(isMemberPointer() && "Invalid accessor");
624 const MemberPointerData
&MPD
=
625 *((const MemberPointerData
*)(const char *)Data
.buffer
);
626 return llvm::makeArrayRef(MPD
.getPath(), MPD
.PathLength
);
629 void APValue::MakeLValue() {
630 assert(isUninit() && "Bad state change");
631 static_assert(sizeof(LV
) <= DataSize
, "LV too big");
632 new ((void*)(char*)Data
.buffer
) LV();
636 void APValue::MakeArray(unsigned InitElts
, unsigned Size
) {
637 assert(isUninit() && "Bad state change");
638 new ((void*)(char*)Data
.buffer
) Arr(InitElts
, Size
);
642 void APValue::MakeMemberPointer(const ValueDecl
*Member
, bool IsDerivedMember
,
643 ArrayRef
<const CXXRecordDecl
*> Path
) {
644 assert(isUninit() && "Bad state change");
645 MemberPointerData
*MPD
= new ((void*)(char*)Data
.buffer
) MemberPointerData
;
646 Kind
= MemberPointer
;
647 MPD
->MemberAndIsDerivedMember
.setPointer(Member
);
648 MPD
->MemberAndIsDerivedMember
.setInt(IsDerivedMember
);
649 MPD
->resizePath(Path
.size());
650 memcpy(MPD
->getPath(), Path
.data(), Path
.size()*sizeof(const CXXRecordDecl
*));