diff options
author | Anna Zaks <ganna@apple.com> | 2012-04-16 21:51:09 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2012-04-16 21:51:09 +0000 |
commit | 51244c22be6ddc9cc19e241e3a3550d3b429b65f (patch) | |
tree | d0585c2bf623e9d08e6a799049a9ccd2f57dd328 /clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp | |
parent | 43195d55d73b05c6d14c411190f8df9a24d34222 (diff) | |
download | bcm5719-llvm-51244c22be6ddc9cc19e241e3a3550d3b429b65f.tar.gz bcm5719-llvm-51244c22be6ddc9cc19e241e3a3550d3b429b65f.zip |
[analyzer] Fix a false alarm in SelfInitChecker (radar://11235991).
Along with it, fix a couple of other corner cases and add more tests.
llvm-svn: 154866
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index d15c8ba408a..97b58cf79b0 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -183,9 +183,6 @@ static void checkForInvalidSelf(const Expr *E, CheckerContext &C, void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg, CheckerContext &C) const { - CallOrObjCMessage MsgWrapper(msg, C.getState(), C.getLocationContext()); - checkPostStmt(MsgWrapper, C); - // When encountering a message that does initialization (init rule), // tag the return value so that we know later on that if self has this value // then it is properly initialized. @@ -209,6 +206,9 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg, return; } + CallOrObjCMessage MsgWrapper(msg, C.getState(), C.getLocationContext()); + checkPostStmt(MsgWrapper, C); + // We don't check for an invalid 'self' in an obj-c message expression to cut // down false positives where logging functions get information from self // (like its class) or doing "invalidation" on self when the initialization @@ -277,6 +277,11 @@ void ObjCSelfInitChecker::checkPreStmt(const CallOrObjCMessage &CE, CheckerContext &C) const { ProgramStateRef state = C.getState(); unsigned NumArgs = CE.getNumArgs(); + // If we passed 'self' as and argument to the call, record it in the state + // to be propagated after the call. + // Note, we could have just given up, but try to be more optimistic here and + // assume that the functions are going to continue initialization or will not + // modify self. for (unsigned i = 0; i < NumArgs; ++i) { SVal argV = CE.getArgSVal(i); if (isSelfVar(argV, C)) { @@ -298,14 +303,24 @@ void ObjCSelfInitChecker::checkPostStmt(const CallOrObjCMessage &CE, for (unsigned i = 0; i < NumArgs; ++i) { SVal argV = CE.getArgSVal(i); if (isSelfVar(argV, C)) { + // If the address of 'self' is being passed to the call, assume that the + // 'self' after the call will have the same flags. + // EX: log(&self) SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>(); state = state->remove<PreCallSelfFlags>(); addSelfFlag(state, state->getSVal(cast<Loc>(argV)), prevFlags, C); return; } else if (hasSelfFlag(argV, SelfFlag_Self, C)) { + // If 'self' is passed to the call by value, assume that the function + // returns 'self'. So assign the flags, which were set on 'self' to the + // return value. + // EX: self = performMoreInitialization(self) SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>(); state = state->remove<PreCallSelfFlags>(); - addSelfFlag(state, state->getSVal(cast<Loc>(argV)), prevFlags, C); + const Expr *CallExpr = CE.getOriginExpr(); + if (CallExpr) + addSelfFlag(state, state->getSVal(CallExpr, C.getLocationContext()), + prevFlags, C); return; } } @@ -358,7 +373,7 @@ static bool isSelfVar(SVal location, CheckerContext &C) { return false; loc::MemRegionVal MRV = cast<loc::MemRegionVal>(location); - if (const DeclRegion *DR = dyn_cast<DeclRegion>(MRV.getRegion())) + if (const DeclRegion *DR = dyn_cast<DeclRegion>(MRV.stripCasts())) return (DR->getDecl() == analCtx->getSelfDecl()); return false; |