diff options
| author | Devin Coughlin <dcoughlin@apple.com> | 2016-12-15 21:27:06 +0000 |
|---|---|---|
| committer | Devin Coughlin <dcoughlin@apple.com> | 2016-12-15 21:27:06 +0000 |
| commit | 64c01f7bef8d65716f12e7556238ea8f8c2c010e (patch) | |
| tree | 41fb79676ba342a7cfb2638af738338f2b0d25ec /clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | |
| parent | 6698c15cb64c5a6b27521466ab8565a906b2323f (diff) | |
| download | bcm5719-llvm-64c01f7bef8d65716f12e7556238ea8f8c2c010e.tar.gz bcm5719-llvm-64c01f7bef8d65716f12e7556238ea8f8c2c010e.zip | |
[analyzer] Add a new SVal to support pointer-to-member operations.
Add a new type of NonLoc SVal for C++ pointer-to-member operations. This SVal
supports both pointers to member functions and pointers to member data.
A patch by Kirill Romanenkov!
Differential Revision: https://reviews.llvm.org/D25475
llvm-svn: 289873
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index edcf2aabc82..28b43dd566d 100644 --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -69,6 +69,9 @@ SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) { bool isLocType = Loc::isLocType(castTy); + if (val.getAs<nonloc::PointerToMember>()) + return val; + if (Optional<nonloc::LocAsInteger> LI = val.getAs<nonloc::LocAsInteger>()) { if (isLocType) return LI->getLoc(); @@ -335,6 +338,21 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state, switch (lhs.getSubKind()) { default: return makeSymExprValNN(state, op, lhs, rhs, resultTy); + case nonloc::PointerToMemberKind: { + assert(rhs.getSubKind() == nonloc::PointerToMemberKind && + "Both SVals should have pointer-to-member-type"); + auto LPTM = lhs.castAs<nonloc::PointerToMember>(), + RPTM = rhs.castAs<nonloc::PointerToMember>(); + auto LPTMD = LPTM.getPTMData(), RPTMD = RPTM.getPTMData(); + switch (op) { + case BO_EQ: + return makeTruthVal(LPTMD == RPTMD, resultTy); + case BO_NE: + return makeTruthVal(LPTMD != RPTMD, resultTy); + default: + return UnknownVal(); + } + } case nonloc::LocAsIntegerKind: { Loc lhsL = lhs.castAs<nonloc::LocAsInteger>().getLoc(); switch (rhs.getSubKind()) { @@ -863,6 +881,23 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state, SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy) { + if (op >= BO_PtrMemD && op <= BO_PtrMemI) { + if (auto PTMSV = rhs.getAs<nonloc::PointerToMember>()) { + if (PTMSV->isNullMemberPointer()) + return UndefinedVal(); + if (const FieldDecl *FD = PTMSV->getDeclAs<FieldDecl>()) { + SVal Result = lhs; + + for (const auto &I : *PTMSV) + Result = StateMgr.getStoreManager().evalDerivedToBase( + Result, I->getType(),I->isVirtual()); + return state->getLValue(FD, Result); + } + } + + return rhs; + } + assert(!BinaryOperator::isComparisonOp(op) && "arguments to comparison ops must be of the same type"); |

