aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-01-25 00:04:03 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-01-25 00:04:03 +0000
commit14429b918bd2f4cb52abc75546a7fe37142054ca (patch)
tree4e827248b9a645d660c677319ea7b929f50fb300 /lib/StaticAnalyzer/Checkers/ExprEngine.cpp
parent5286e2ddfd8332520de4c076e49991d6fe557adb (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.cpp58
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);