19 #include "llvm/Support/ErrorHandling.h" 20 #include "llvm/Support/raw_ostream.h" 21 using namespace clang;
26 : T(T->getCanonicalTypeUnqualified().getTypePtr()) {}
38 "Type is insufficiently aligned");
41 : Ptr(P), Local{I, V} {}
43 : Ptr(P),
Local{I, V} {}
54 return is<TypeInfoLValue>() ? 0 :
Local.CallIndex;
58 return is<TypeInfoLValue>() ? 0 :
Local.Version;
62 assert(is<TypeInfoLValue>() &&
"not a type_info lvalue");
69 if (LHS.Ptr != RHS.Ptr)
73 return LHS.
Local.CallIndex == RHS.
Local.CallIndex &&
84 bool IsOnePastTheEnd : 1;
89 return Ptr.getOpaqueValue();
96 APValue::LValueBase::operator
bool ()
const {
97 return static_cast<bool>(Ptr);
133 static const unsigned InlinePathSpace =
144 LV() { PathLength = (unsigned)-1; }
148 if (Length == PathLength)
157 bool hasPath()
const {
return PathLength != (unsigned)-1; }
158 bool hasPathPtr()
const {
return hasPath() && PathLength > InlinePathSpace; }
162 return hasPathPtr() ? PathPtr : Path;
167 struct MemberPointerBase {
168 llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember;
174 static const unsigned InlinePathSpace =
175 (DataSize -
sizeof(MemberPointerBase)) /
sizeof(
const CXXRecordDecl*);
178 PathElem Path[InlinePathSpace];
186 if (Length == PathLength)
192 PathPtr =
new PathElem[Length];
195 bool hasPathPtr()
const {
return PathLength > InlinePathSpace; }
197 PathElem *
getPath() {
return hasPathPtr() ? PathPtr : Path; }
199 return hasPathPtr() ? PathPtr : Path;
205 APValue::Arr::Arr(
unsigned NumElts,
unsigned Size) :
206 Elts(
new APValue[NumElts + (NumElts != Size ? 1 : 0)]),
207 NumElts(NumElts), ArrSize(Size) {}
208 APValue::Arr::~Arr() {
delete [] Elts; }
210 APValue::StructData::StructData(
unsigned NumBases,
unsigned NumFields) :
211 Elts(
new APValue[NumBases+NumFields]),
212 NumBases(NumBases), NumFields(NumFields) {}
213 APValue::StructData::~StructData() {
217 APValue::UnionData::UnionData() : Field(
nullptr),
Value(
new APValue) {}
218 APValue::UnionData::~UnionData () {
238 MakeFixedPoint(std::move(FXCopy));
243 setVector(((
const Vec *)(
const char *)RHS.Data.buffer)->Elts,
293 void APValue::DestroyDataAndMakeUninit() {
295 ((APSInt*)(
char*)Data.buffer)->~APSInt();
297 ((APFloat*)(
char*)Data.buffer)->~APFloat();
301 ((Vec*)(
char*)Data.buffer)->~Vec();
303 ((ComplexAPSInt*)(
char*)Data.buffer)->~ComplexAPSInt();
305 ((ComplexAPFloat*)(
char*)Data.buffer)->~ComplexAPFloat();
307 ((
LV*)(
char*)Data.buffer)->~
LV();
309 ((Arr*)(
char*)Data.buffer)->~Arr();
311 ((StructData*)(
char*)Data.buffer)->~StructData();
313 ((UnionData*)(
char*)Data.buffer)->~UnionData();
317 ((AddrLabelDiffData*)(
char*)Data.buffer)->~AddrLabelDiffData();
333 return getInt().needsCleanup();
341 "In _Complex float types, real and imaginary values always have the " 347 "In _Complex int types, real and imaginary values must have the " 351 return reinterpret_cast<const LV *
>(Data.buffer)->hasPathPtr();
356 llvm_unreachable(
"Unknown APValue kind!");
360 std::swap(
Kind, RHS.Kind);
361 char TmpData[DataSize];
362 memcpy(TmpData, Data.buffer, DataSize);
363 memcpy(Data.buffer, RHS.Data.buffer, DataSize);
364 memcpy(RHS.Data.buffer, TmpData, DataSize);
369 llvm::errs() <<
'\n';
375 V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
377 return V.convertToDouble();
386 OS <<
"Indeterminate";
389 OS <<
"Int: " <<
getInt();
413 OS <<
"LValue: <todo>";
431 for (
unsigned I = 1; I != N; ++I) {
439 for (
unsigned I = 1; I != N; ++I) {
450 OS <<
"MemberPointer: <todo>";
453 OS <<
"AddrLabelDiff: <todo>";
456 llvm_unreachable(
"Unknown APValue kind!");
463 Out <<
"<out of lifetime>";
466 Out <<
"<uninitialized>";
470 Out << (
getInt().getBoolValue() ?
"true" :
"false");
508 Out << (Ctx.
getLangOpts().CPlusPlus11 ?
"nullptr" :
"0");
509 }
else if (IsReference) {
531 }
else if (!IsReference)
539 assert(Base.
get<
const Expr *>() !=
nullptr &&
540 "Expecting non-null Expr");
546 Out <<
" + " << (O / S);
562 ElemTy = VD->getType();
568 assert(E !=
nullptr &&
"Expecting non-null Expr");
575 for (
unsigned I = 0, N = Path.size(); I != N; ++I) {
579 const Decl *BaseOrMember = Path[I].getAsBaseOrMember().getPointer();
580 if (
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
584 const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
587 Out << *CastToBase <<
"::";
589 ElemTy = VD->getType();
593 Out <<
'[' << Path[I].getAsArrayIndex() <<
']';
614 for (
unsigned I = 1; I != N; ++I) {
634 for (
unsigned I = 0; I != N; ++I, ++BI) {
642 for (
const auto *FI : RD->
fields()) {
645 if (FI->isUnnamedBitfield())
continue;
656 Out <<
"." << *FD <<
" = ";
665 Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) <<
"::" << *VD;
676 llvm_unreachable(
"Unknown APValue kind!");
681 llvm::raw_string_ostream Out(Result);
708 assert(
isLValue() &&
"Invalid accessor");
709 return ((
const LV*)(
const void*)Data.buffer)->Base;
713 assert(
isLValue() &&
"Invalid accessor");
714 return ((
const LV*)(
const void*)Data.buffer)->IsOnePastTheEnd;
718 assert(
isLValue() &&
"Invalid accessor");
719 return ((
LV*)(
void*)Data.buffer)->Offset;
723 assert(
isLValue() &&
"Invalid accessor");
724 return ((
const LV*)(
const char*)Data.buffer)->hasPath();
729 const LV &LVal = *((
const LV*)(
const char*)Data.buffer);
730 return llvm::makeArrayRef(LVal.
getPath(), LVal.PathLength);
734 assert(
isLValue() &&
"Invalid accessor");
735 return ((
const LV*)(
const char*)Data.buffer)->Base.getCallIndex();
739 assert(
isLValue() &&
"Invalid accessor");
740 return ((
const LV*)(
const char*)Data.buffer)->Base.getVersion();
744 assert(
isLValue() &&
"Invalid usage");
745 return ((
const LV*)(
const char*)Data.buffer)->IsNullPtr;
750 assert(
isLValue() &&
"Invalid accessor");
751 LV &LVal = *((
LV*)(
char*)Data.buffer);
753 LVal.IsOnePastTheEnd =
false;
756 LVal.IsNullPtr = IsNullPtr;
762 assert(
isLValue() &&
"Invalid accessor");
763 LV &LVal = *((
LV*)(
char*)Data.buffer);
765 LVal.IsOnePastTheEnd = IsOnePastTheEnd;
769 LVal.IsNullPtr = IsNullPtr;
776 return MPD.MemberAndIsDerivedMember.getPointer();
783 return MPD.MemberAndIsDerivedMember.getInt();
790 return llvm::makeArrayRef(MPD.
getPath(), MPD.PathLength);
793 void APValue::MakeLValue() {
794 assert(
isAbsent() &&
"Bad state change");
795 static_assert(
sizeof(
LV) <= DataSize,
"LV too big");
796 new ((
void*)(
char*)Data.buffer)
LV();
800 void APValue::MakeArray(
unsigned InitElts,
unsigned Size) {
801 assert(
isAbsent() &&
"Bad state change");
802 new ((
void*)(
char*)Data.buffer) Arr(InitElts, Size);
806 void APValue::MakeMemberPointer(
const ValueDecl *Member,
bool IsDerivedMember,
808 assert(
isAbsent() &&
"Bad state change");
811 MPD->MemberAndIsDerivedMember.setPointer(Member);
812 MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
unsigned getStructNumFields() const
Defines the clang::ASTContext interface.
void resizePath(unsigned Length)
friend llvm::hash_code hash_value(const LValueBase &Base)
friend bool operator==(const LValueBase &LHS, const LValueBase &RHS)
A (possibly-)qualified type.
llvm::APSInt getValue() const
unsigned getCallIndex() const
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...
The base class of the type hierarchy.
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)
QualType getTypeInfoType() const
Describes how types, statements, expressions, and declarations should be printed. ...
bool isLValueOnePastTheEnd() const
const ValueDecl * getMemberPointerDecl() const
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
Represents a member of a struct/union/class.
bool isReferenceType() const
const PathElem * getPath() const
unsigned getArraySize() const
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const
Make an APSInt of the appropriate width and signedness for the given Value and integer Type...
unsigned getLValueCallIndex() const
Symbolic representation of typeid(T) for some type T.
void * TypeInfoType
The type std::type_info, if this is a TypeInfoLValue.
llvm::hash_code hash_value(const APValue::LValueBase &Base)
CharUnits - This is an opaque type for sizes expressed in character units.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
const clang::PrintingPolicy & getPrintingPolicy() const
base_class_iterator bases_begin()
LValuePathEntry * PathPtr
bool needsCleanup() const
Returns whether the object performed allocations.
void * getAsOpaquePtr() const
APSInt & getComplexIntReal()
APValue & getVectorElt(unsigned I)
The APFixedPoint class works similarly to APInt/APSInt in that it is a functional replacement for a s...
unsigned getLValueVersion() const
static CharUnits One()
One - Construct a CharUnits quantity of one.
unsigned getVersion() const
bool hasLValuePath() const
APValue & getArrayFiller()
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
bool hasArrayFiller() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
This represents one expression.
const Type * getType() const
std::string getAsString(const ASTContext &Ctx, QualType Ty) const
A non-discriminated union of a base, field, or array index.
static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo)
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)
This object has an indeterminate value (C++ [basic.indet]).
const LValueBase getLValueBase() const
void * getOpaqueValue() const
void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, bool IsNullPtr)
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()
void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
static QualType getFromOpaquePtr(const void *Ptr)
bool isMemberPointerToDerivedMember() const
StreamedQualTypeHelper stream(const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Dataflow Directional Tag Classes.
void swap(APValue &RHS)
Swaps the contents of this and the given APValue.
bool isBooleanType() const
unsigned getArrayInitializedElts() const
bool toIntegralConstant(APSInt &Result, QualType SrcTy, const ASTContext &Ctx) const
Try to convert this value to an integral constant.
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...
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).
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\, const ASTContext *Context=nullptr) const
ValueKind getKind() const
APFloat & getComplexFloatImag()
Represents a C++ struct/union/class.
There is no such object (it's outside its lifetime).
base_class_iterator bases_end()
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
uint64_t getTargetNullPointerValue(QualType QT) const
Get target-dependent integer value for null pointer which is used for constant folding.
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)
const LangOptions & getLangOpts() const
APFixedPoint & getFixedPoint()
void setComplexFloat(APFloat R, APFloat I)
CharUnits & getLValueOffset()
unsigned getVectorLength() const