diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2012-05-03 16:53:59 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2012-05-03 16:53:59 +0000 | 
| commit | 6b9a6e390fbb92c40eb9c6ac9e7abbd88dd7a767 (patch) | |
| tree | 2e51705e103e92c7be1b21e8bd8ffd5b5d0e4d52 /lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp | |
| parent | dbe13110f59f48b4dbb7552b3ac2935acdeece7f (diff) | |
Notes
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp')
| -rw-r--r-- | lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp | 25 | 
1 files changed, 20 insertions, 5 deletions
diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index d15c8ba408a4..97b58cf79b0e 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/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;  | 
