aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-05-08 21:19:21 +0000
committerAnna Zaks <ganna@apple.com>2012-05-08 21:19:21 +0000
commit66843480a64a9f23f2a23118d92aa3dd6260af0c (patch)
tree22b4768885f4c94b6d0ea38e7a1f157b1066da58 /clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
parent92f6adc8befc032ab6d442a0d121a67573d6f91e (diff)
downloadllvm-66843480a64a9f23f2a23118d92aa3dd6260af0c.zip
llvm-66843480a64a9f23f2a23118d92aa3dd6260af0c.tar.gz
llvm-66843480a64a9f23f2a23118d92aa3dd6260af0c.tar.bz2
[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. llvm-svn: 156420
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp26
1 files changed, 25 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index 97b58cf..89340cc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/clang/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)