diff options
Diffstat (limited to 'lib/AST/APValue.cpp')
-rw-r--r-- | lib/AST/APValue.cpp | 121 |
1 files changed, 105 insertions, 16 deletions
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index 146ebad055..b99a66267c 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -21,7 +21,7 @@ using namespace clang; namespace { struct LVBase { - APValue::LValueBase Base; + llvm::PointerIntPair<APValue::LValueBase, 1, bool> BaseAndIsOnePastTheEnd; CharUnits Offset; unsigned PathLength; }; @@ -40,12 +40,17 @@ struct APValue::LV : LVBase { }; LV() { PathLength = (unsigned)-1; } - ~LV() { if (hasPathPtr()) delete [] PathPtr; } + ~LV() { resizePath(0); } - void allocPath() { - if (hasPathPtr()) PathPtr = new LValuePathEntry[PathLength]; + void resizePath(unsigned Length) { + if (Length == PathLength) + return; + if (hasPathPtr()) + delete [] PathPtr; + PathLength = Length; + if (hasPathPtr()) + PathPtr = new LValuePathEntry[Length]; } - void freePath() { if (hasPathPtr()) delete [] PathPtr; } bool hasPath() const { return PathLength != (unsigned)-1; } bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; } @@ -56,6 +61,43 @@ struct APValue::LV : LVBase { } }; +namespace { + struct MemberPointerBase { + llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember; + unsigned PathLength; + }; +} + +struct APValue::MemberPointerData : MemberPointerBase { + static const unsigned InlinePathSpace = + (MaxSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); + typedef const CXXRecordDecl *PathElem; + union { + PathElem Path[InlinePathSpace]; + PathElem *PathPtr; + }; + + MemberPointerData() { PathLength = 0; } + ~MemberPointerData() { resizePath(0); } + + void resizePath(unsigned Length) { + if (Length == PathLength) + return; + if (hasPathPtr()) + delete [] PathPtr; + PathLength = Length; + if (hasPathPtr()) + PathPtr = new PathElem[Length]; + } + + bool hasPathPtr() const { return PathLength > InlinePathSpace; } + + PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; } + const PathElem *getPath() const { + return hasPathPtr() ? PathPtr : Path; + } +}; + // FIXME: Reduce the malloc traffic here. APValue::Arr::Arr(unsigned NumElts, unsigned Size) : @@ -78,7 +120,8 @@ APValue::UnionData::~UnionData () { const APValue &APValue::operator=(const APValue &RHS) { if (this == &RHS) return *this; - if (Kind != RHS.Kind || Kind == Array || Kind == Struct) { + if (Kind != RHS.Kind || Kind == Array || Kind == Struct || + Kind == MemberPointer) { MakeUninit(); if (RHS.isInt()) MakeInt(); @@ -98,6 +141,10 @@ const APValue &APValue::operator=(const APValue &RHS) { MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields()); else if (RHS.isUnion()) MakeUnion(); + else if (RHS.isMemberPointer()) + MakeMemberPointer(RHS.getMemberPointerDecl(), + RHS.isMemberPointerToDerivedMember(), + RHS.getMemberPointerPath()); } if (isInt()) setInt(RHS.getInt()); @@ -112,7 +159,8 @@ const APValue &APValue::operator=(const APValue &RHS) { setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag()); else if (isLValue()) { if (RHS.hasLValuePath()) - setLValue(RHS.getLValueBase(), RHS.getLValueOffset(),RHS.getLValuePath()); + setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), + RHS.isLValueOnePastTheEnd()); else setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath()); } else if (isArray()) { @@ -149,6 +197,8 @@ void APValue::MakeUninit() { ((StructData*)(char*)Data)->~StructData(); else if (Kind == Union) ((UnionData*)(char*)Data)->~UnionData(); + else if (Kind == MemberPointer) + ((MemberPointerData*)(char*)Data)->~MemberPointerData(); Kind = Uninitialized; } @@ -217,6 +267,9 @@ void APValue::print(raw_ostream &OS) const { case Union: OS << "Union: " << getUnionValue(); return; + case MemberPointer: + OS << "MemberPointer: <todo>"; + return; } llvm_unreachable("Unknown APValue kind!"); } @@ -280,6 +333,9 @@ static void WriteShortAPValueToStream(raw_ostream& Out, case APValue::Union: Out << '{' << V.getUnionValue() << '}'; return; + case APValue::MemberPointer: + Out << "MemberPointer: <todo>"; + return; } llvm_unreachable("Unknown APValue kind!"); } @@ -294,7 +350,12 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, const APValue::LValueBase APValue::getLValueBase() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data)->Base; + return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getPointer(); +} + +bool APValue::isLValueOnePastTheEnd() const { + assert(isLValue() && "Invalid accessor"); + return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getInt(); } CharUnits &APValue::getLValueOffset() { @@ -316,24 +377,41 @@ ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath) { assert(isLValue() && "Invalid accessor"); LV &LVal = *((LV*)(char*)Data); - LVal.freePath(); - LVal.Base = B; + LVal.BaseAndIsOnePastTheEnd.setPointer(B); + LVal.BaseAndIsOnePastTheEnd.setInt(false); LVal.Offset = O; - LVal.PathLength = (unsigned)-1; + LVal.resizePath((unsigned)-1); } void APValue::setLValue(LValueBase B, const CharUnits &O, - ArrayRef<LValuePathEntry> Path) { + ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd) { assert(isLValue() && "Invalid accessor"); LV &LVal = *((LV*)(char*)Data); - LVal.freePath(); - LVal.Base = B; + LVal.BaseAndIsOnePastTheEnd.setPointer(B); + LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd); LVal.Offset = O; - LVal.PathLength = Path.size(); - LVal.allocPath(); + LVal.resizePath(Path.size()); memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); } +const ValueDecl *APValue::getMemberPointerDecl() const { + assert(isMemberPointer() && "Invalid accessor"); + const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + return MPD.MemberAndIsDerivedMember.getPointer(); +} + +bool APValue::isMemberPointerToDerivedMember() const { + assert(isMemberPointer() && "Invalid accessor"); + const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + return MPD.MemberAndIsDerivedMember.getInt(); +} + +ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { + assert(isMemberPointer() && "Invalid accessor"); + const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength); +} + void APValue::MakeLValue() { assert(isUninit() && "Bad state change"); assert(sizeof(LV) <= MaxSize && "LV too big"); @@ -346,3 +424,14 @@ void APValue::MakeArray(unsigned InitElts, unsigned Size) { new ((void*)(char*)Data) Arr(InitElts, Size); Kind = Array; } + +void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef<const CXXRecordDecl*> Path) { + assert(isUninit() && "Bad state change"); + MemberPointerData *MPD = new ((void*)(char*)Data) MemberPointerData; + Kind = MemberPointer; + MPD->MemberAndIsDerivedMember.setPointer(Member); + MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); + MPD->resizePath(Path.size()); + memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*)); +} |