diff options
Diffstat (limited to 'include/clang/AST/APValue.h')
-rw-r--r-- | include/clang/AST/APValue.h | 269 |
1 files changed, 233 insertions, 36 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index 375af28f0c56e..1b6e90cf4a830 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -17,14 +17,24 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" namespace clang { + class AddrLabelExpr; + class ASTContext; class CharUnits; class DiagnosticBuilder; class Expr; + class FieldDecl; + class Decl; + class ValueDecl; + class CXXRecordDecl; + class QualType; /// APValue - This class implements a discriminated union of [uninitialized] -/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset]. +/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], +/// [Vector: N * APValue], [Array: N * APValue] class APValue { typedef llvm::APSInt APSInt; typedef llvm::APFloat APFloat; @@ -36,8 +46,25 @@ public: ComplexInt, ComplexFloat, LValue, - Vector + Vector, + Array, + Struct, + Union, + MemberPointer, + AddrLabelDiff }; + typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase; + typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; + union LValuePathEntry { + /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item + /// in the path. An opaque value of type BaseOrMemberType. + void *BaseOrMember; + /// ArrayIndex - The array index of the next item in the path. + uint64_t ArrayIndex; + }; + struct NoLValuePath {}; + struct UninitArray {}; + struct UninitStruct {}; private: ValueKind Kind; @@ -49,13 +76,37 @@ private: APFloat Real, Imag; ComplexAPFloat() : Real(0.0), Imag(0.0) {} }; - + struct LV; struct Vec { APValue *Elts; unsigned NumElts; Vec() : Elts(0), NumElts(0) {} ~Vec() { delete[] Elts; } }; + struct Arr { + APValue *Elts; + unsigned NumElts, ArrSize; + Arr(unsigned NumElts, unsigned ArrSize); + ~Arr(); + }; + struct StructData { + APValue *Elts; + unsigned NumBases; + unsigned NumFields; + StructData(unsigned NumBases, unsigned NumFields); + ~StructData(); + }; + struct UnionData { + const FieldDecl *Field; + APValue *Value; + UnionData(); + ~UnionData(); + }; + struct AddrLabelDiffData { + const AddrLabelExpr* LHSExpr; + const AddrLabelExpr* RHSExpr; + }; + struct MemberPointerData; enum { MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ? @@ -84,18 +135,42 @@ public: APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) { MakeComplexFloat(); setComplexFloat(R, I); } - APValue(const APValue &RHS) : Kind(Uninitialized) { - *this = RHS; + APValue(const APValue &RHS); + APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex) + : Kind(Uninitialized) { + MakeLValue(); setLValue(B, O, N, CallIndex); + } + APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, + bool OnePastTheEnd, unsigned CallIndex) + : Kind(Uninitialized) { + MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex); } - APValue(const Expr* B, const CharUnits &O) : Kind(Uninitialized) { - MakeLValue(); setLValue(B, O); + APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { + MakeArray(InitElts, Size); + } + APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) { + MakeStruct(B, M); + } + explicit APValue(const FieldDecl *D, const APValue &V = APValue()) + : Kind(Uninitialized) { + MakeUnion(); setUnion(D, V); + } + APValue(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) { + MakeMemberPointer(Member, IsDerivedMember, Path); + } + APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) + : Kind(Uninitialized) { + MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr); } - APValue(const Expr* B); ~APValue() { MakeUninit(); } + /// \brief Swaps the contents of this and the given APValue. + void swap(APValue &RHS); + ValueKind getKind() const { return Kind; } bool isUninit() const { return Kind == Uninitialized; } bool isInt() const { return Kind == Int; } @@ -104,9 +179,17 @@ public: bool isComplexFloat() const { return Kind == ComplexFloat; } bool isLValue() const { return Kind == LValue; } bool isVector() const { return Kind == Vector; } + bool isArray() const { return Kind == Array; } + bool isStruct() const { return Kind == Struct; } + bool isUnion() const { return Kind == Union; } + bool isMemberPointer() const { return Kind == MemberPointer; } + bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; } - void print(raw_ostream &OS) const; void dump() const; + void dump(raw_ostream &OS) const; + + void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const; + std::string getAsString(ASTContext &Ctx, QualType Ty) const; APSInt &getInt() { assert(isInt() && "Invalid accessor"); @@ -124,19 +207,6 @@ public: return const_cast<APValue*>(this)->getFloat(); } - APValue &getVectorElt(unsigned i) { - assert(isVector() && "Invalid accessor"); - return ((Vec*)(char*)Data)->Elts[i]; - } - const APValue &getVectorElt(unsigned i) const { - assert(isVector() && "Invalid accessor"); - return ((const Vec*)(const char*)Data)->Elts[i]; - } - unsigned getVectorLength() const { - assert(isVector() && "Invalid accessor"); - return ((const Vec*)(const void *)Data)->NumElts; - } - APSInt &getComplexIntReal() { assert(isComplexInt() && "Invalid accessor"); return ((ComplexAPSInt*)(char*)Data)->Real; @@ -169,8 +239,104 @@ public: return const_cast<APValue*>(this)->getComplexFloatImag(); } - const Expr* getLValueBase() const; - CharUnits getLValueOffset() const; + const LValueBase getLValueBase() const; + CharUnits &getLValueOffset(); + const CharUnits &getLValueOffset() const { + return const_cast<APValue*>(this)->getLValueOffset(); + } + bool isLValueOnePastTheEnd() const; + bool hasLValuePath() const; + ArrayRef<LValuePathEntry> getLValuePath() const; + unsigned getLValueCallIndex() const; + + APValue &getVectorElt(unsigned I) { + assert(isVector() && "Invalid accessor"); + assert(I < getVectorLength() && "Index out of range"); + return ((Vec*)(char*)Data)->Elts[I]; + } + const APValue &getVectorElt(unsigned I) const { + return const_cast<APValue*>(this)->getVectorElt(I); + } + unsigned getVectorLength() const { + assert(isVector() && "Invalid accessor"); + return ((const Vec*)(const void *)Data)->NumElts; + } + + APValue &getArrayInitializedElt(unsigned I) { + assert(isArray() && "Invalid accessor"); + assert(I < getArrayInitializedElts() && "Index out of range"); + return ((Arr*)(char*)Data)->Elts[I]; + } + const APValue &getArrayInitializedElt(unsigned I) const { + return const_cast<APValue*>(this)->getArrayInitializedElt(I); + } + bool hasArrayFiller() const { + return getArrayInitializedElts() != getArraySize(); + } + APValue &getArrayFiller() { + assert(isArray() && "Invalid accessor"); + assert(hasArrayFiller() && "No array filler"); + return ((Arr*)(char*)Data)->Elts[getArrayInitializedElts()]; + } + const APValue &getArrayFiller() const { + return const_cast<APValue*>(this)->getArrayFiller(); + } + unsigned getArrayInitializedElts() const { + assert(isArray() && "Invalid accessor"); + return ((const Arr*)(const void *)Data)->NumElts; + } + unsigned getArraySize() const { + assert(isArray() && "Invalid accessor"); + return ((const Arr*)(const void *)Data)->ArrSize; + } + + unsigned getStructNumBases() const { + assert(isStruct() && "Invalid accessor"); + return ((const StructData*)(const char*)Data)->NumBases; + } + unsigned getStructNumFields() const { + assert(isStruct() && "Invalid accessor"); + return ((const StructData*)(const char*)Data)->NumFields; + } + APValue &getStructBase(unsigned i) { + assert(isStruct() && "Invalid accessor"); + return ((StructData*)(char*)Data)->Elts[i]; + } + APValue &getStructField(unsigned i) { + assert(isStruct() && "Invalid accessor"); + return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i]; + } + const APValue &getStructBase(unsigned i) const { + return const_cast<APValue*>(this)->getStructBase(i); + } + const APValue &getStructField(unsigned i) const { + return const_cast<APValue*>(this)->getStructField(i); + } + + const FieldDecl *getUnionField() const { + assert(isUnion() && "Invalid accessor"); + return ((const UnionData*)(const char*)Data)->Field; + } + APValue &getUnionValue() { + assert(isUnion() && "Invalid accessor"); + return *((UnionData*)(char*)Data)->Value; + } + const APValue &getUnionValue() const { + return const_cast<APValue*>(this)->getUnionValue(); + } + + const ValueDecl *getMemberPointerDecl() const; + bool isMemberPointerToDerivedMember() const; + ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const; + + const AddrLabelExpr* getAddrLabelDiffLHS() const { + assert(isAddrLabelDiff() && "Invalid accessor"); + return ((const AddrLabelDiffData*)(const char*)Data)->LHSExpr; + } + const AddrLabelExpr* getAddrLabelDiffRHS() const { + assert(isAddrLabelDiff() && "Invalid accessor"); + return ((const AddrLabelDiffData*)(const char*)Data)->RHSExpr; + } void setInt(const APSInt &I) { assert(isInt() && "Invalid accessor"); @@ -201,12 +367,34 @@ public: ((ComplexAPFloat*)(char*)Data)->Real = R; ((ComplexAPFloat*)(char*)Data)->Imag = I; } - void setLValue(const Expr *B, const CharUnits &O); + void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, + unsigned CallIndex); + void setLValue(LValueBase B, const CharUnits &O, + ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, + unsigned CallIndex); + void setUnion(const FieldDecl *Field, const APValue &Value) { + assert(isUnion() && "Invalid accessor"); + ((UnionData*)(char*)Data)->Field = Field; + *((UnionData*)(char*)Data)->Value = Value; + } + void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, + const AddrLabelExpr* RHSExpr) { + ((AddrLabelDiffData*)(char*)Data)->LHSExpr = LHSExpr; + ((AddrLabelDiffData*)(char*)Data)->RHSExpr = RHSExpr; + } - const APValue &operator=(const APValue &RHS); + /// Assign by swapping from a copy of the RHS. + APValue &operator=(APValue RHS) { + swap(RHS); + return *this; + } private: - void MakeUninit(); + void DestroyDataAndMakeUninit(); + void MakeUninit() { + if (Kind != Uninitialized) + DestroyDataAndMakeUninit(); + } void MakeInt() { assert(isUninit() && "Bad state change"); new ((void*)Data) APSInt(1); @@ -233,17 +421,26 @@ private: Kind = ComplexFloat; } void MakeLValue(); + void MakeArray(unsigned InitElts, unsigned Size); + void MakeStruct(unsigned B, unsigned M) { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) StructData(B, M); + Kind = Struct; + } + void MakeUnion() { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) UnionData(); + Kind = Union; + } + void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef<const CXXRecordDecl*> Path); + void MakeAddrLabelDiff() { + assert(isUninit() && "Bad state change"); + new ((void*)(char*)Data) AddrLabelDiffData(); + Kind = AddrLabelDiff; + } }; -inline raw_ostream &operator<<(raw_ostream &OS, const APValue &V) { - V.print(OS); - return OS; -} - -// Writes a concise representation of V to DB, in a single << operation. -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const APValue &V); - } // end namespace clang. #endif |