diff options
-rw-r--r-- | include/clang/AST/APValue.h | 13 | ||||
-rw-r--r-- | lib/AST/APValue.cpp | 89 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 10 |
3 files changed, 64 insertions, 48 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index b7e588fba4..1b6e90cf4a 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -135,9 +135,7 @@ 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); @@ -170,6 +168,9 @@ public: 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; } @@ -382,7 +383,11 @@ public: ((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 DestroyDataAndMakeUninit(); diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index 976629cea2..0b5b3b0a5e 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -122,71 +122,68 @@ APValue::UnionData::~UnionData () { delete Value; } -const APValue &APValue::operator=(const APValue &RHS) { - if (this == &RHS) - return *this; - if (Kind != RHS.Kind || Kind == Array || Kind == Struct || - Kind == MemberPointer) { - MakeUninit(); - if (RHS.isInt()) - MakeInt(); - else if (RHS.isFloat()) - MakeFloat(); - else if (RHS.isVector()) - MakeVector(); - else if (RHS.isComplexInt()) - MakeComplexInt(); - else if (RHS.isComplexFloat()) - MakeComplexFloat(); - else if (RHS.isLValue()) - MakeLValue(); - else if (RHS.isArray()) - MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); - else if (RHS.isStruct()) - MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields()); - else if (RHS.isUnion()) - MakeUnion(); - else if (RHS.isMemberPointer()) - MakeMemberPointer(RHS.getMemberPointerDecl(), - RHS.isMemberPointerToDerivedMember(), - RHS.getMemberPointerPath()); - else if (RHS.isAddrLabelDiff()) - MakeAddrLabelDiff(); - } - if (isInt()) +APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { + switch (RHS.getKind()) { + case Uninitialized: + break; + case Int: + MakeInt(); setInt(RHS.getInt()); - else if (isFloat()) + break; + case Float: + MakeFloat(); setFloat(RHS.getFloat()); - else if (isVector()) + break; + case Vector: + MakeVector(); setVector(((const Vec *)(const char *)RHS.Data)->Elts, RHS.getVectorLength()); - else if (isComplexInt()) + break; + case ComplexInt: + MakeComplexInt(); setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag()); - else if (isComplexFloat()) + break; + case ComplexFloat: + MakeComplexFloat(); setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag()); - else if (isLValue()) { + break; + case LValue: + MakeLValue(); if (RHS.hasLValuePath()) setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(), RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex()); else setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(), RHS.getLValueCallIndex()); - } else if (isArray()) { + break; + case Array: + MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize()); for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I) getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I); if (RHS.hasArrayFiller()) getArrayFiller() = RHS.getArrayFiller(); - } else if (isStruct()) { + break; + case Struct: + MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields()); for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I) getStructBase(I) = RHS.getStructBase(I); for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I) getStructField(I) = RHS.getStructField(I); - } else if (isUnion()) { + break; + case Union: + MakeUnion(); setUnion(RHS.getUnionField(), RHS.getUnionValue()); - } else if (isAddrLabelDiff()) { + break; + case MemberPointer: + MakeMemberPointer(RHS.getMemberPointerDecl(), + RHS.isMemberPointerToDerivedMember(), + RHS.getMemberPointerPath()); + break; + case AddrLabelDiff: + MakeAddrLabelDiff(); setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS()); + break; } - return *this; } void APValue::DestroyDataAndMakeUninit() { @@ -215,6 +212,14 @@ void APValue::DestroyDataAndMakeUninit() { Kind = Uninitialized; } +void APValue::swap(APValue &RHS) { + std::swap(Kind, RHS.Kind); + char TmpData[MaxSize]; + memcpy(TmpData, Data, MaxSize); + memcpy(Data, RHS.Data, MaxSize); + memcpy(RHS.Data, TmpData, MaxSize); +} + void APValue::dump() const { dump(llvm::errs()); llvm::errs() << '\n'; diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 5f9b0501b2..97c906c407 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1518,7 +1518,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, // This object might be initialized later. return false; - const APValue *O = &Obj; + APValue *O = &Obj; // Walk the designator's path to find the subobject. for (unsigned I = 0, N = Sub.Entries.size(); I != N; ++I) { if (ObjType->isArrayType()) { @@ -1616,7 +1616,13 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, } } - Obj = APValue(*O); + // This may look super-stupid, but it serves an important purpose: if we just + // swapped Obj and *O, we'd create an object which had itself as a subobject. + // To avoid the leak, we ensure that Tmp ends up owning the original complete + // object, which is destroyed by Tmp's destructor. + APValue Tmp; + O->swap(Tmp); + Obj.swap(Tmp); return true; } |