20 #include "llvm/Support/ErrorHandling.h" 21 #include "llvm/Support/raw_ostream.h" 22 using namespace clang;
26 llvm::PointerIntPair<APValue::LValueBase, 1, bool> BaseAndIsOnePastTheEnd;
35 static const unsigned InlinePathSpace =
46 LV() { PathLength = (unsigned)-1; }
47 ~LV() { resizePath(0); }
50 if (Length == PathLength)
59 bool hasPath()
const {
return PathLength != (unsigned)-1; }
60 bool hasPathPtr()
const {
return hasPath() && PathLength > InlinePathSpace; }
64 return hasPathPtr() ? PathPtr : Path;
69 struct MemberPointerBase {
70 llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember;
76 static const unsigned InlinePathSpace =
77 (DataSize -
sizeof(MemberPointerBase)) /
sizeof(
const CXXRecordDecl*);
80 PathElem Path[InlinePathSpace];
88 if (Length == PathLength)
94 PathPtr =
new PathElem[Length];
97 bool hasPathPtr()
const {
return PathLength > InlinePathSpace; }
99 PathElem *
getPath() {
return hasPathPtr() ? PathPtr : Path; }
101 return hasPathPtr() ? PathPtr : Path;
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; }
112 APValue::StructData::StructData(
unsigned NumBases,
unsigned NumFields) :
113 Elts(
new APValue[NumBases+NumFields]),
114 NumBases(NumBases), NumFields(NumFields) {}
115 APValue::StructData::~StructData() {
119 APValue::UnionData::UnionData() : Field(
nullptr),
Value(
new APValue) {}
120 APValue::UnionData::~UnionData () {
138 setVector(((
const Vec *)(
const char *)RHS.Data.buffer)->Elts,
189 void APValue::DestroyDataAndMakeUninit() {
191 ((APSInt*)(
char*)Data.buffer)->~APSInt();
193 ((APFloat*)(
char*)Data.buffer)->~APFloat();
195 ((Vec*)(
char*)Data.buffer)->~Vec();
197 ((ComplexAPSInt*)(
char*)Data.buffer)->~ComplexAPSInt();
199 ((ComplexAPFloat*)(
char*)Data.buffer)->~ComplexAPFloat();
201 ((
LV*)(
char*)Data.buffer)->~
LV();
203 ((Arr*)(
char*)Data.buffer)->~Arr();
205 ((StructData*)(
char*)Data.buffer)->~StructData();
207 ((UnionData*)(
char*)Data.buffer)->~UnionData();
211 ((AddrLabelDiffData*)(
char*)Data.buffer)->~AddrLabelDiffData();
226 return getInt().needsCleanup();
232 "In _Complex float types, real and imaginary values always have the " 238 "In _Complex int types, real and imaginary values must have the " 242 return reinterpret_cast<const LV *
>(Data.buffer)->hasPathPtr();
247 llvm_unreachable(
"Unknown APValue kind!");
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);
260 llvm::errs() <<
'\n';
266 V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
268 return V.convertToDouble();
274 OS <<
"Uninitialized";
277 OS <<
"Int: " <<
getInt();
298 OS <<
"LValue: <todo>";
316 for (
unsigned I = 1; I != N; ++I) {
324 for (
unsigned I = 1; I != N; ++I) {
335 OS <<
"MemberPointer: <todo>";
338 OS <<
"AddrLabelDiff: <todo>";
341 llvm_unreachable(
"Unknown APValue kind!");
347 Out <<
"<uninitialized>";
351 Out << (
getInt().getBoolValue() ?
"true" :
"false");
401 }
else if (!IsReference)
407 assert(Base.get<
const Expr *>() !=
nullptr &&
408 "Expecting non-null Expr");
414 Out <<
" + " << (O / S);
430 ElemTy = VD->getType();
432 const Expr *E = Base.get<
const Expr*>();
433 assert(E !=
nullptr &&
"Expecting non-null Expr");
440 for (
unsigned I = 0, N = Path.size(); I != N; ++I) {
444 const Decl *BaseOrMember =
445 BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer();
446 if (
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
450 const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
453 Out << *CastToBase <<
"::";
455 ElemTy = VD->getType();
459 Out <<
'[' << Path[I].ArrayIndex <<
']';
480 for (
unsigned I = 1; I != N; ++I) {
500 for (
unsigned I = 0; I != N; ++I, ++BI) {
508 for (
const auto *FI : RD->
fields()) {
511 if (FI->isUnnamedBitfield())
continue;
522 Out <<
"." << *FD <<
" = ";
531 Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) <<
"::" << *VD;
542 llvm_unreachable(
"Unknown APValue kind!");
547 llvm::raw_string_ostream Out(Result);
554 assert(
isLValue() &&
"Invalid accessor");
555 return ((
const LV*)(
const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getPointer();
559 assert(
isLValue() &&
"Invalid accessor");
560 return ((
const LV*)(
const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getInt();
564 assert(
isLValue() &&
"Invalid accessor");
565 return ((
LV*)(
void*)Data.buffer)->Offset;
569 assert(
isLValue() &&
"Invalid accessor");
570 return ((
const LV*)(
const char*)Data.buffer)->hasPath();
575 const LV &LVal = *((
const LV*)(
const char*)Data.buffer);
576 return llvm::makeArrayRef(LVal.
getPath(), LVal.PathLength);
580 assert(
isLValue() &&
"Invalid accessor");
581 return ((
const LV*)(
const char*)Data.buffer)->CallIndex;
585 assert(
isLValue() &&
"Invalid usage");
586 return ((
const LV*)(
const char*)Data.buffer)->IsNullPtr;
590 unsigned CallIndex,
bool IsNullPtr) {
591 assert(
isLValue() &&
"Invalid accessor");
592 LV &LVal = *((
LV*)(
char*)Data.buffer);
593 LVal.BaseAndIsOnePastTheEnd.setPointer(B);
594 LVal.BaseAndIsOnePastTheEnd.setInt(
false);
596 LVal.CallIndex = CallIndex;
598 LVal.IsNullPtr = IsNullPtr;
603 unsigned CallIndex,
bool IsNullPtr) {
604 assert(
isLValue() &&
"Invalid accessor");
605 LV &LVal = *((
LV*)(
char*)Data.buffer);
606 LVal.BaseAndIsOnePastTheEnd.setPointer(B);
607 LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd);
609 LVal.CallIndex = CallIndex;
612 LVal.IsNullPtr = IsNullPtr;
619 return MPD.MemberAndIsDerivedMember.getPointer();
626 return MPD.MemberAndIsDerivedMember.getInt();
633 return llvm::makeArrayRef(MPD.
getPath(), MPD.PathLength);
636 void APValue::MakeLValue() {
637 assert(
isUninit() &&
"Bad state change");
638 static_assert(
sizeof(
LV) <= DataSize,
"LV too big");
639 new ((
void*)(
char*)Data.buffer)
LV();
643 void APValue::MakeArray(
unsigned InitElts,
unsigned Size) {
644 assert(
isUninit() &&
"Bad state change");
645 new ((
void*)(
char*)Data.buffer) Arr(InitElts, Size);
649 void APValue::MakeMemberPointer(
const ValueDecl *Member,
bool IsDerivedMember,
651 assert(
isUninit() &&
"Bad state change");
654 MPD->MemberAndIsDerivedMember.setPointer(Member);
655 MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
unsigned getStructNumFields() const
Defines the clang::ASTContext interface.
void resizePath(unsigned Length)
A (possibly-)qualified type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
C Language Family Type Representation.
Decl - This represents one declaration (or definition), e.g.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
bool isZero() const
isZero - Test whether the quantity equals zero.
const LValuePathEntry * getPath() const
const AddrLabelExpr * getAddrLabelDiffLHS() const
QualType getElementType() const
APFloat & getComplexFloatReal()
const T * getAs() const
Member-template getAs<specific type>'.
ArrayRef< LValuePathEntry > getLValuePath() const
static double GetApproxValue(const llvm::APFloat &F)
bool isLValueOnePastTheEnd() const
const ValueDecl * getMemberPointerDecl() const
RecordDecl - Represents a struct/union/class.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
field_range fields() const
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
bool isReferenceType() const
const PathElem * getPath() const
unsigned getArraySize() const
unsigned getLValueCallIndex() const
CharUnits - This is an opaque type for sizes expressed in character units.
const clang::PrintingPolicy & getPrintingPolicy() const
std::string getAsString(ASTContext &Ctx, QualType Ty) const
void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, const ASTContext *Context=nullptr) const
base_class_iterator bases_begin()
LValuePathEntry * PathPtr
bool needsCleanup() const
Returns whether the object performed allocations.
APSInt & getComplexIntReal()
APValue & getVectorElt(unsigned I)
static CharUnits One()
One - Construct a CharUnits quantity of one.
bool hasLValuePath() const
APValue & getArrayFiller()
bool hasArrayFiller() const
ValueDecl - Represent the declaration of a variable (in which case it is an lvalue) a function (in wh...
Expr - This represents one expression.
APValue & getStructField(unsigned i)
QualType getRecordType(const RecordDecl *Decl) const
Represents a GCC generic vector type.
bool isNullPointer() const
APSInt & getComplexIntImag()
The result type of a method or function.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const FieldDecl * getUnionField() const
void setVector(const APValue *E, unsigned N)
APValue & getStructBase(unsigned i)
unsigned getStructNumBases() const
APValue & getArrayInitializedElt(unsigned I)
const LValueBase getLValueBase() const
const AddrLabelExpr * getAddrLabelDiffRHS() const
APValue & getUnionValue()
bool isMemberPointer() const
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
void setAddrLabelDiff(const AddrLabelExpr *LHSExpr, const AddrLabelExpr *RHSExpr)
LValuePathEntry * getPath()
bool isMemberPointerToDerivedMember() const
Dataflow Directional Tag Classes.
void swap(APValue &RHS)
Swaps the contents of this and the given APValue.
bool isBooleanType() const
unsigned getArrayInitializedElts() const
ArrayRef< const CXXRecordDecl * > getMemberPointerPath() const
void resizePath(unsigned Length)
LabelDecl * getLabel() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
llvm::PointerUnion< const ValueDecl *, const Expr * > LValueBase
const CXXRecordDecl * PathElem
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat]...
Represents a base class of a C++ class.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
ValueKind getKind() const
APFloat & getComplexFloatImag()
Represents a C++ struct/union/class.
void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, unsigned CallIndex, bool IsNullPtr)
base_class_iterator bases_end()
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
void setComplexInt(APSInt R, APSInt I)
void setUnion(const FieldDecl *Field, const APValue &Value)
void setComplexFloat(APFloat R, APFloat I)
CharUnits & getLValueOffset()
unsigned getVectorLength() const