diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-01-25 00:04:03 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-01-25 00:04:03 +0000 |
commit | 14429b918bd2f4cb52abc75546a7fe37142054ca (patch) | |
tree | 4e827248b9a645d660c677319ea7b929f50fb300 /lib/StaticAnalyzer/Checkers/ExprEngine.cpp | |
parent | 5286e2ddfd8332520de4c076e49991d6fe557adb (diff) |
[analyzer] Handle the dot syntax for properties in the ExprEngine.
We translate property accesses to obj-c messages by simulating "loads" or "stores" to properties
using a pseudo-location SVal kind (ObjCPropRef).
Checkers can now reason about obj-c messages for both explicit message expressions and implicit
messages due to property accesses.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124161 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/ExprEngine.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ExprEngine.cpp | 58 |
1 files changed, 52 insertions, 6 deletions
diff --git a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp index 9a74bd99a1..53931dc607 100644 --- a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp @@ -865,6 +865,10 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst); break; + case Stmt::ObjCPropertyRefExprClass: + VisitObjCPropertyRefExpr(cast<ObjCPropertyRefExpr>(S), Pred, Dst); + break; + // Cases not handled yet; but will handle some day. case Stmt::DesignatedInitExprClass: case Stmt::ExtVectorElementExprClass: @@ -875,7 +879,6 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, case Stmt::ObjCAtTryStmtClass: case Stmt::ObjCEncodeExprClass: case Stmt::ObjCIsaExprClass: - case Stmt::ObjCPropertyRefExprClass: case Stmt::ObjCProtocolExprClass: case Stmt::ObjCSelectorExprClass: case Stmt::ObjCStringLiteralClass: @@ -1799,6 +1802,17 @@ void ExprEngine::evalStore(ExplodedNodeSet& Dst, const Expr *AssignE, assert(Builder && "StmtNodeBuilder must be defined."); + // Proceed with the store. We use AssignE as the anchor for the PostStore + // ProgramPoint if it is non-NULL, and LocationE otherwise. + const Expr *StoreE = AssignE ? AssignE : LocationE; + + if (isa<loc::ObjCPropRef>(location)) { + loc::ObjCPropRef prop = cast<loc::ObjCPropRef>(location); + ExplodedNodeSet src = Pred; + return VisitObjCMessage(ObjCPropertySetter(prop.getPropRefExpr(), + StoreE, Val), src, Dst); + } + // Evaluate the location (checks for bad dereferences). ExplodedNodeSet Tmp; evalLocation(Tmp, LocationE, Pred, state, location, tag, false); @@ -1811,10 +1825,6 @@ void ExprEngine::evalStore(ExplodedNodeSet& Dst, const Expr *AssignE, SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind, ProgramPoint::PostStoreKind); - // Proceed with the store. We use AssignE as the anchor for the PostStore - // ProgramPoint if it is non-NULL, and LocationE otherwise. - const Expr *StoreE = AssignE ? AssignE : LocationE; - for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) evalBind(Dst, StoreE, *NI, GetState(*NI), location, Val); } @@ -1825,6 +1835,13 @@ void ExprEngine::evalLoad(ExplodedNodeSet& Dst, const Expr *Ex, const void *tag, QualType LoadTy) { assert(!isa<NonLoc>(location) && "location cannot be a NonLoc."); + if (isa<loc::ObjCPropRef>(location)) { + loc::ObjCPropRef prop = cast<loc::ObjCPropRef>(location); + ExplodedNodeSet src = Pred; + return VisitObjCMessage(ObjCPropertyGetter(prop.getPropRefExpr(), Ex), + src, Dst); + } + // Are we loading from a region? This actually results in two loads; one // to fetch the address of the referenced value and one to fetch the // referenced value. @@ -2048,6 +2065,34 @@ void ExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred, } //===----------------------------------------------------------------------===// +// Transfer function: Objective-C dot-syntax to access a property. +//===----------------------------------------------------------------------===// + +void ExprEngine::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Ex, + ExplodedNode *Pred, + ExplodedNodeSet &Dst) { + + // Visit the base expression, which is needed for computing the lvalue + // of the ivar. + ExplodedNodeSet dstBase; + const Expr *baseExpr = Ex->getBase(); + Visit(baseExpr, Pred, dstBase); + + ExplodedNodeSet dstPropRef; + + // Using the base, compute the lvalue of the instance variable. + for (ExplodedNodeSet::iterator I = dstBase.begin(), E = dstBase.end(); + I!=E; ++I) { + ExplodedNode *nodeBase = *I; + const GRState *state = GetState(nodeBase); + SVal baseVal = state->getSVal(baseExpr); + MakeNode(dstPropRef, Ex, *I, state->BindExpr(Ex, loc::ObjCPropRef(Ex))); + } + + Dst.insert(dstPropRef); +} + +//===----------------------------------------------------------------------===// // Transfer function: Objective-C ivar references. //===----------------------------------------------------------------------===// @@ -2426,7 +2471,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNodeSet S2; CheckerVisit(CastE, S2, S1, PreVisitStmtCallback); - if (CastE->getCastKind() == CK_LValueToRValue) { + if (CastE->getCastKind() == CK_LValueToRValue || + CastE->getCastKind() == CK_GetObjCProperty) { for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I!=E; ++I) { ExplodedNode *subExprNode = *I; const GRState *state = GetState(subExprNode); |