[cfe-commits] r159563 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp test/Analysis/misc-ps-region-store.m test/Analysis/nonnull.m

Anna Zaks ganna at apple.com
Mon Jul 16 13:28:13 PDT 2012


On Jul 2, 2012, at 12:28 PM, Jordan Rose wrote:

> Author: jrose
> Date: Mon Jul  2 14:28:21 2012
> New Revision: 159563
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=159563&view=rev
> Log:
> [analyzer] Convert existing checkers to use check::preCall and check::postCall.
> 
> Added:
>    cfe/trunk/test/Analysis/nonnull.m
> Modified:
>    cfe/trunk/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
>    cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
>    cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
>    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
>    cfe/trunk/test/Analysis/misc-ps-region-store.m
> 
> Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp?rev=159563&r1=159562&r2=159563&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp Mon Jul  2 14:28:21 2012
> @@ -15,6 +15,7 @@
> #include "ClangSACheckers.h"
> #include "clang/StaticAnalyzer/Core/Checker.h"
> #include "clang/StaticAnalyzer/Core/CheckerManager.h"
> +#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
> #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
> #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
> 
> @@ -23,40 +24,32 @@
> 
> namespace {
> class AttrNonNullChecker
> -  : public Checker< check::PreStmt<CallExpr> > {
> +  : public Checker< check::PreCall > {
>   mutable OwningPtr<BugType> BT;
> public:
> 
> -  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
> +  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
> };
> } // end anonymous namespace
> 
> -void AttrNonNullChecker::checkPreStmt(const CallExpr *CE,
> +void AttrNonNullChecker::checkPreCall(const CallEvent &Call,
>                                       CheckerContext &C) const {
> -  ProgramStateRef state = C.getState();
> -  const LocationContext *LCtx = C.getLocationContext();
> -
> -  // Check if the callee has a 'nonnull' attribute.
> -  SVal X = state->getSVal(CE->getCallee(), LCtx);
> -
> -  const FunctionDecl *FD = X.getAsFunctionDecl();
> +  const Decl *FD = Call.getDecl();
>   if (!FD)
>     return;
> 
> -  const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
> +  const NonNullAttr *Att = FD->getAttr<NonNullAttr>();
>   if (!Att)
>     return;
> 
> -  // Iterate through the arguments of CE and check them for null.
> -  unsigned idx = 0;
> -
> -  for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
> -       ++I, ++idx) {
> +  ProgramStateRef state = C.getState();
> 
> +  // Iterate through the arguments of CE and check them for null.
> +  for (unsigned idx = 0, count = Call.getNumArgs(); idx != count; ++idx) {
>     if (!Att->isNonNull(idx))
>       continue;
> 
> -    SVal V = state->getSVal(*I, LCtx);
> +    SVal V = Call.getArgSVal(idx);
>     DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
> 
>     // If the value is unknown or undefined, we can't perform this check.
> @@ -65,11 +58,16 @@
> 
>     if (!isa<Loc>(*DV)) {
>       // If the argument is a union type, we want to handle a potential
> -      // transparent_unoin GCC extension.
> -      QualType T = (*I)->getType();
> +      // transparent_union GCC extension.
> +      const Expr *ArgE = Call.getArgExpr(idx);
> +      if (!ArgE)
> +        continue;
> +
> +      QualType T = ArgE->getType();
>       const RecordType *UT = T->getAsUnionType();
>       if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
>         continue;
> +
>       if (nonloc::CompoundVal *CSV = dyn_cast<nonloc::CompoundVal>(DV)) {
>         nonloc::CompoundVal::iterator CSV_I = CSV->begin();
>         assert(CSV_I != CSV->end());
> @@ -78,8 +76,7 @@
>         assert(++CSV_I == CSV->end());
>         if (!DV)
>           continue;        
> -      }
> -      else {
> +      } else {
>         // FIXME: Handle LazyCompoundVals?
>         continue;
>       }
> @@ -106,10 +103,10 @@
>                              "'nonnull' parameter", errorNode);
> 
>         // Highlight the range of the argument that was null.
> -        const Expr *arg = *I;
> -        R->addRange(arg->getSourceRange());
> -        R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(errorNode,
> -                                                                   arg, R));
> +        R->addRange(Call.getArgSourceRange(idx));
> +        if (const Expr *ArgE = Call.getArgExpr(idx))
> +          R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(errorNode,
> +                                                                     ArgE, R));
>         // Emit the bug report.
>         C.EmitReport(R);
>       }
> 
> Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp?rev=159563&r1=159562&r2=159563&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp Mon Jul  2 14:28:21 2012
> @@ -27,7 +27,8 @@
> 
> namespace {
> class CallAndMessageChecker
> -  : public Checker< check::PreStmt<CallExpr>, check::PreObjCMessage > {
> +  : public Checker< check::PreStmt<CallExpr>, check::PreObjCMessage,
> +                    check::PreCall > {
>   mutable OwningPtr<BugType> BT_call_null;
>   mutable OwningPtr<BugType> BT_call_undef;
>   mutable OwningPtr<BugType> BT_call_arg;
> @@ -39,15 +40,13 @@
> 
>   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
>   void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;
> +  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
> 
> private:
> -  static void PreVisitProcessArgs(CheckerContext &C, const CallEvent &Call,
> -                             const char *BT_desc, OwningPtr<BugType> &BT);
> -  static bool PreVisitProcessArg(CheckerContext &C, SVal V,SourceRange argRange,
> -                                 const Expr *argEx,
> +  static bool PreVisitProcessArg(CheckerContext &C, SVal V,
> +                                 SourceRange argRange, const Expr *argEx,
>                                  const bool checkUninitFields,
> -                                 const char *BT_desc,
> -                                 OwningPtr<BugType> &BT);
> +                                 const char *BT_desc, OwningPtr<BugType> &BT);
> 
>   static void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
>   void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg,
> @@ -76,26 +75,6 @@
>   C.EmitReport(R);
> }
> 
> -void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C,
> -                                                const CallEvent &Call,
> -                                                const char *BT_desc,
> -                                                OwningPtr<BugType> &BT) {
> -  // Don't check for uninitialized field values in arguments if the
> -  // caller has a body that is available and we have the chance to inline it.
> -  // This is a hack, but is a reasonable compromise betweens sometimes warning
> -  // and sometimes not depending on if we decide to inline a function.
> -  const Decl *D = Call.getDecl();
> -  const bool checkUninitFields =
> -    !(C.getAnalysisManager().shouldInlineCall() &&
> -      (D && D->getBody()));
> -  
> -  for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i)
> -    if (PreVisitProcessArg(C, Call.getArgSVal(i),
> -                           Call.getArgSourceRange(i), Call.getArgExpr(i),
> -                           checkUninitFields, BT_desc, BT))
> -      return;
> -}
> -
> bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
>                                                SVal V, SourceRange argRange,
>                                                const Expr *argEx,
> @@ -104,10 +83,10 @@
>                                                OwningPtr<BugType> &BT) {
>   if (V.isUndef()) {
>     if (ExplodedNode *N = C.generateSink()) {
> -      LazyInit_BT(BT_desc, BT);
> +      LazyInit_BT("Uninitialized argument value", BT);
> 
>       // Generate a report for this bug.
> -      BugReport *R = new BugReport(*BT, BT->getName(), N);
> +      BugReport *R = new BugReport(*BT, BT_desc, N);
>       R->addRange(argRange);
>       if (argEx)
>         R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, argEx,
> @@ -227,24 +206,47 @@
>         new BuiltinBug("Called function pointer is null (null dereference)"));
>     EmitBadCall(BT_call_null.get(), C, CE);
>   }
> +}
> 
> -  // FIXME: This tree of switching can go away if/when we add a check::postCall.
> -  if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
> -    BlockCall Call(CE, State, LCtx);
> -    PreVisitProcessArgs(C, Call,
> -                        "Block call argument is an uninitialized value",
> -                        BT_call_arg);
> -  } else if (const CXXMemberCallExpr *me = dyn_cast<CXXMemberCallExpr>(CE)) {
> -    CXXMemberCall Call(me, State, LCtx);
> -    PreVisitProcessArgs(C, Call,
> -                        "Function call argument is an uninitialized value",
> -                        BT_call_arg);
> -  } else {
> -    FunctionCall Call(CE, State, LCtx);
> -    PreVisitProcessArgs(C, Call,
> -                        "Function call argument is an uninitialized value",
> -                        BT_call_arg);
> +void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
> +                                         CheckerContext &C) const {
> +  // Don't check for uninitialized field values in arguments if the
> +  // caller has a body that is available and we have the chance to inline it.
> +  // This is a hack, but is a reasonable compromise betweens sometimes warning
> +  // and sometimes not depending on if we decide to inline a function.
> +  const Decl *D = Call.getDecl();
> +  const bool checkUninitFields =
> +    !(C.getAnalysisManager().shouldInlineCall() &&
> +      (D && D->getBody()));
> +
> +  OwningPtr<BugType> *BT;
> +  const char *Desc;
> +
> +  switch (Call.getKind()) {
> +  case CE_ObjCPropertyAccess:
> +    BT = &BT_msg_arg;
> +    // Getters do not have arguments, so we don't need to worry about this.
> +    Desc = "Argument for property setter is an uninitialized value";
> +    break;
> +  case CE_ObjCMessage:
> +    BT = &BT_msg_arg;
> +    Desc = "Argument in message expression is an uninitialized value";
> +    break;
> +  case CE_Block:
> +    BT = &BT_call_arg;
> +    Desc = "Block call argument is an uninitialized value";
> +    break;
> +  default:
> +    BT = &BT_call_arg;
> +    Desc = "Function call argument is an uninitialized value";
> +    break;
>   }

Can we only switch/perform bug description assignment if we know there is an error?

> +
> +  for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i)
> +    if (PreVisitProcessArg(C, Call.getArgSVal(i),
> +                           Call.getArgSourceRange(i), Call.getArgExpr(i),
> +                           checkUninitFields, Desc, *BT))
> +      return;
> }
> 
> void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
> @@ -289,15 +291,6 @@
>       return;
>     }
>   }
> -
> -  const char *bugDesc = "Argument in message expression is an "
> -                        "uninitialized value";
> -  if (const ObjCPropertyAccess *Prop = dyn_cast<ObjCPropertyAccess>(&msg))
> -    if (Prop->isSetter())
> -      bugDesc = "Argument for property setter is an uninitialized value";
> -
> -  // Check for any arguments that are uninitialized/undefined.
> -  PreVisitProcessArgs(C, msg, bugDesc, BT_msg_arg);
> }
> 
> void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
> 
> Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp?rev=159563&r1=159562&r2=159563&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp Mon Jul  2 14:28:21 2012
> @@ -54,27 +54,23 @@
> static bool isSelfVar(SVal location, CheckerContext &C);
> 
> namespace {
> -class ObjCSelfInitChecker : public Checker<  check::PreObjCMessage,
> -                                             check::PostObjCMessage,
> +class ObjCSelfInitChecker : public Checker<  check::PostObjCMessage,
>                                              check::PostStmt<ObjCIvarRefExpr>,
>                                              check::PreStmt<ReturnStmt>,
> -                                             check::PreStmt<CallExpr>,
> -                                             check::PostStmt<CallExpr>,
> +                                             check::PreCall,
> +                                             check::PostCall,
>                                              check::Location,
>                                              check::Bind > {
> public:
> -  void checkPreObjCMessage(const ObjCMethodCall &Msg, CheckerContext &C) const;
>   void checkPostObjCMessage(const ObjCMethodCall &Msg, CheckerContext &C) const;
>   void checkPostStmt(const ObjCIvarRefExpr *E, CheckerContext &C) const;
>   void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
> -  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
> -  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 CallEvent &CE, CheckerContext &C) const;
> -  void checkPostStmt(const CallEvent &CE, CheckerContext &C) const;
> +  void checkPreCall(const CallEvent &CE, CheckerContext &C) const;
> +  void checkPostCall(const CallEvent &CE, CheckerContext &C) const;
> 
> };
> } // end anonymous namespace
> @@ -208,8 +204,6 @@
>     return;
>   }
> 
> -  checkPostStmt(Msg, 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
> @@ -240,8 +234,8 @@
>                                                  "'[(super or self) init...]'");
> }
> 
> -// When a call receives a reference to 'self', [Pre/Post]VisitGenericCall pass
> -// the SelfFlags from the object 'self' point to before the call, to the new
> +// When a call receives a reference to 'self', [Pre/Post]Call pass
> +// the SelfFlags from the object 'self' points to before the call to the new
> // object after the call. This is to avoid invalidation of 'self' by logging
> // functions.
> // Another common pattern in classes with multiple initializers is to put the
> @@ -256,53 +250,13 @@
> // Until we can use inter-procedural analysis, in such a call, transfer the
> // SelfFlags to the result of the call.
> 
> -void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
> +void ObjCSelfInitChecker::checkPreCall(const CallEvent &CE,
>                                        CheckerContext &C) const {
> -  // FIXME: This tree of switching can go away if/when we add a check::postCall.
> -  const Expr *Callee = CE->getCallee()->IgnoreParens();
> -  ProgramStateRef State = C.getState();
> -  const LocationContext *LCtx = C.getLocationContext();
> -  SVal L = State->getSVal(Callee, LCtx);
> -
> -  if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
> -    BlockCall Call(CE, State, LCtx);
> -    checkPreStmt(Call, C);
> -  } else if (const CXXMemberCallExpr *me = dyn_cast<CXXMemberCallExpr>(CE)) {
> -    CXXMemberCall Call(me, State, LCtx);
> -    checkPreStmt(Call, C);
> -  } else {
> -    FunctionCall Call(CE, State, LCtx);
> -    checkPreStmt(Call, C);
> -  }
> -}
> -
> -void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
> -                                        CheckerContext &C) const {
> -  // FIXME: This tree of switching can go away if/when we add a check::postCall.
> -  const Expr *Callee = CE->getCallee()->IgnoreParens();
> -  ProgramStateRef State = C.getState();
> -  const LocationContext *LCtx = C.getLocationContext();
> -  SVal L = State->getSVal(Callee, LCtx);
> -
> -  if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
> -    BlockCall Call(CE, State, LCtx);
> -    checkPostStmt(Call, C);
> -  } else if (const CXXMemberCallExpr *me = dyn_cast<CXXMemberCallExpr>(CE)) {
> -    CXXMemberCall Call(me, State, LCtx);
> -    checkPostStmt(Call, C);
> -  } else {
> -    FunctionCall Call(CE, State, LCtx);
> -    checkPostStmt(Call, C);
> -  }
> -}
> -
> -void ObjCSelfInitChecker::checkPreObjCMessage(const ObjCMethodCall &Msg,
> -                                              CheckerContext &C) const {
> -  checkPreStmt(Msg, C);
> -}
> +  // FIXME: A callback should disable checkers at the start of functions.
> +  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
> +                                 C.getCurrentAnalysisDeclContext()->getDecl())))
> +    return;
> 
> -void ObjCSelfInitChecker::checkPreStmt(const CallEvent &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
> @@ -324,9 +278,19 @@
>   }
> }
> 
> -void ObjCSelfInitChecker::checkPostStmt(const CallEvent &CE,
> +void ObjCSelfInitChecker::checkPostCall(const CallEvent &CE,
>                                         CheckerContext &C) const {
> +  // FIXME: A callback should disable checkers at the start of functions.
> +  if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
> +                                 C.getCurrentAnalysisDeclContext()->getDecl())))
> +    return;
> +
>   ProgramStateRef state = C.getState();
> +  SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
> +  if (!prevFlags)
> +    return;
> +  state = state->remove<PreCallSelfFlags>();
> +
>   unsigned NumArgs = CE.getNumArgs();
>   for (unsigned i = 0; i < NumArgs; ++i) {
>     SVal argV = CE.getArgSVal(i);
> @@ -334,8 +298,6 @@
>       // 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)) {
> @@ -343,8 +305,6 @@
>       // 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>();
>       const Expr *CallExpr = CE.getOriginExpr();
>       if (CallExpr)
>         addSelfFlag(state, state->getSVal(CallExpr, C.getLocationContext()),
> 
> Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=159563&r1=159562&r2=159563&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Mon Jul  2 14:28:21 2012
> @@ -2379,12 +2379,10 @@
>                     check::EndPath,
>                     check::PostStmt<BlockExpr>,
>                     check::PostStmt<CastExpr>,
> -                    check::PostStmt<CallExpr>,
> -                    check::PostStmt<CXXConstructExpr>,
>                     check::PostStmt<ObjCArrayLiteral>,
>                     check::PostStmt<ObjCDictionaryLiteral>,
>                     check::PostStmt<ObjCBoxedExpr>,
> -                    check::PostObjCMessage,
> +                    check::PostCall,
>                     check::PreStmt<ReturnStmt>,
>                     check::RegionChanges,
>                     eval::Assume,
> @@ -2523,13 +2521,11 @@
>   void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
>   void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
> 
> -  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
> -  void checkPostStmt(const CXXConstructExpr *CE, CheckerContext &C) const;
>   void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
>   void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
>   void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
> 
> -  void checkPostObjCMessage(const ObjCMethodCall &Msg, CheckerContext &C) const;
> +  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
> 
>   void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
>                     CheckerContext &C) const;
> @@ -2685,54 +2681,6 @@
>   C.addTransition(state);
> }
> 
> -void RetainCountChecker::checkPostStmt(const CallExpr *CE,
> -                                       CheckerContext &C) const {
> -  if (C.wasInlined)
> -    return;
> -  
> -  // Get the callee.
> -  ProgramStateRef state = C.getState();
> -  const Expr *Callee = CE->getCallee();
> -  SVal L = state->getSVal(Callee, C.getLocationContext());
> -
> -  RetainSummaryManager &Summaries = getSummaryManager(C);
> -
> -  // FIXME: This tree of switching can go away if/when we add a check::postCall.
> -  if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
> -    // FIXME: Better support for blocks.  For now we stop tracking anything
> -    // that is passed to blocks.
> -    // FIXME: Need to handle variables that are "captured" by the block.
> -    BlockCall Call(CE, state, C.getLocationContext());
> -    const RetainSummary *Summ = Summaries.getSummary(Call, state);
> -    checkSummary(*Summ, Call, C);
> -
> -  } else if (const CXXMemberCallExpr *me = dyn_cast<CXXMemberCallExpr>(CE)) {
> -    CXXMemberCall Call(me, state, C.getLocationContext());
> -    const RetainSummary *Summ = Summaries.getSummary(Call, state);
> -    checkSummary(*Summ, Call, C);
> -
> -  } else {
> -    FunctionCall Call(CE, state, C.getLocationContext());
> -    const RetainSummary *Summ = Summaries.getSummary(Call, state);
> -    checkSummary(*Summ, Call, C);
> -  }
> -}
> -
> -void RetainCountChecker::checkPostStmt(const CXXConstructExpr *CE,
> -                                       CheckerContext &C) const {
> -  const CXXConstructorDecl *Ctor = CE->getConstructor();
> -  if (!Ctor)
> -    return;
> -
> -  RetainSummaryManager &Summaries = getSummaryManager(C);
> -  ProgramStateRef state = C.getState();
> -  CXXConstructorCall Call(CE, state, C.getLocationContext());
> -
> -  const RetainSummary *Summ = Summaries.getSummary(Call, state);
> -
> -  checkSummary(*Summ, Call, C);
> -}
> -
> void RetainCountChecker::processObjCLiterals(CheckerContext &C,
>                                              const Expr *Ex) const {
>   ProgramStateRef state = C.getState();
> @@ -2791,12 +2739,14 @@
>   C.addTransition(State);
> }
> 
> -void RetainCountChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
> -                                              CheckerContext &C) const {
> -  RetainSummaryManager &Summaries = getSummaryManager(C);
> -  const RetainSummary *Summ = Summaries.getSummary(Msg, C.getState());
> +void RetainCountChecker::checkPostCall(const CallEvent &Call,
> +                                       CheckerContext &C) const {
> +  if (C.wasInlined)
> +    return;
> 
> -  checkSummary(*Summ, Msg, C);
> +  RetainSummaryManager &Summaries = getSummaryManager(C);
> +  const RetainSummary *Summ = Summaries.getSummary(Call, C.getState());
> +  checkSummary(*Summ, Call, C);
> }
> 
> /// GetReturnType - Used to get the return type of a message expression or
> 
> Modified: cfe/trunk/test/Analysis/misc-ps-region-store.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.m?rev=159563&r1=159562&r2=159563&view=diff
> ==============================================================================
> --- cfe/trunk/test/Analysis/misc-ps-region-store.m (original)
> +++ cfe/trunk/test/Analysis/misc-ps-region-store.m Mon Jul  2 14:28:21 2012
> @@ -673,7 +673,7 @@
>   builder = ^(id object) {
>     id x;
>     if (object) {
> -      builder(x); // expected-warning{{Function call argument is an uninitialized value}}
> +      builder(x); // expected-warning{{Block call argument is an uninitialized value}}
>     }
>   };
>   builder(target);
> 
> Added: cfe/trunk/test/Analysis/nonnull.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/nonnull.m?rev=159563&view=auto
> ==============================================================================
> --- cfe/trunk/test/Analysis/nonnull.m (added)
> +++ cfe/trunk/test/Analysis/nonnull.m Mon Jul  2 14:28:21 2012
> @@ -0,0 +1,23 @@
> +// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s
> +
> + at interface MyObject
> +- (void)takePointer:(void *)ptr __attribute__((nonnull(1)));
> + at end
> +
> +void testNonNullMethod(int *p, MyObject *obj) {
> +  if (p)
> +    return;
> +  [obj takePointer:p]; // expected-warning{{nonnull}}
> +}
> +
> +
> + at interface Subclass : MyObject
> +// [[nonnull]] is an inherited attribute.
> +- (void)takePointer:(void *)ptr;
> + at end
> +
> +void testSubclass(int *p, Subclass *obj) {
> +  if (p)
> +    return;
> +  [obj takePointer:p]; // expected-warning{{nonnull}}
> +}
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits




More information about the cfe-commits mailing list