diff options
author | Anna Zaks <ganna@apple.com> | 2012-05-08 21:19:21 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2012-05-08 21:19:21 +0000 |
commit | 6a2a1865f8bfaedff312b043f1e875a43e95b259 (patch) | |
tree | c100c3595292b053c25ba8343e767d217379959b /lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp | |
parent | 20e181a3ece8862dcfcfacf70763074ddec5a68b (diff) |
[analyzer] SelfInit: Stop tracking self if it's assigned a value we
don't reason about.
Self is just like a local variable in init methods, so it can be
assigned anything like result of static functions, other methods ... So
to suppress false positives that result in such cases, stop tracking the
checker-specific state after self is being assigned to (unless the
value is't being assigned to is either self or conforms to our rules).
This change does not invalidate any existing regression tests.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156420 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index 97b58cf79b..89340cc290 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -60,7 +60,8 @@ class ObjCSelfInitChecker : public Checker< check::PreObjCMessage, check::PreStmt<ReturnStmt>, check::PreStmt<CallExpr>, check::PostStmt<CallExpr>, - check::Location > { + check::Location, + check::Bind > { public: void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; void checkPostObjCMessage(ObjCMessage msg, CheckerContext &C) const; @@ -70,6 +71,7 @@ public: void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; void checkLocation(SVal location, bool isLoad, const Stmt *S, CheckerContext &C) const; + void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const; void checkPreStmt(const CallOrObjCMessage &CE, CheckerContext &C) const; void checkPostStmt(const CallOrObjCMessage &CE, CheckerContext &C) const; @@ -336,6 +338,28 @@ void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad, addSelfFlag(state, state->getSVal(cast<Loc>(location)), SelfFlag_Self, C); } + +void ObjCSelfInitChecker::checkBind(SVal loc, SVal val, const Stmt *S, + CheckerContext &C) const { + // Allow assignment of anything to self. Self is a local variable in the + // initializer, so it is legal to assign anything to it, like results of + // static functions/method calls. After self is assigned something we cannot + // reason about, stop enforcing the rules. + // (Only continue checking if the assigned value should be treated as self.) + if ((isSelfVar(loc, C)) && + !hasSelfFlag(val, SelfFlag_InitRes, C) && + !hasSelfFlag(val, SelfFlag_Self, C) && + !isSelfVar(val, C)) { + + // Stop tracking the checker-specific state in the state. + ProgramStateRef State = C.getState(); + State = State->remove<CalledInit>(); + if (SymbolRef sym = loc.getAsSymbol()) + State = State->remove<SelfFlag>(sym); + C.addTransition(State); + } +} + // FIXME: A callback should disable checkers at the start of functions. static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND) { if (!ND) |