[cfe-commits] r157833 - in /cfe/trunk: include/clang/Analysis/AnalysisContext.h include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h lib/Analysis/AnalysisDeclContext.cpp lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp lib/StaticAnalyzer/Core/MemRegion.cpp lib/StaticAnalyzer/Core/ProgramState.cpp lib/StaticAnalyzer/Core/RegionStore.cpp test/Analysis/blocks.m test/Analysis/inline-plist.c test/Analysis/retain-release.m

Anna Zaks ganna at apple.com
Fri Jun 1 15:48:30 PDT 2012


Shouldn't we run remove dead binding before the block expression for diagnostic location quality?
in ExprEngine.cpp:

static bool shouldRemoveDeadBindings(
.. 
  // Run before processing a call.
  if (isa<CallExpr>(S.getStmt()))
    return true;

Would be great to add a helper method which lists all expressions we might inline which other parts of the analyzer may query. I suspect there are more places like the above.

Anna.
On Jun 1, 2012, at 1:04 PM, Ted Kremenek wrote:

> Author: kremenek
> Date: Fri Jun  1 15:04:04 2012
> New Revision: 157833
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=157833&view=rev
> Log:
> static analyzer: add inlining support for directly called blocks.
> 
> Modified:
>    cfe/trunk/include/clang/Analysis/AnalysisContext.h
>    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
>    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
>    cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
>    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
>    cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
>    cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
>    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
>    cfe/trunk/test/Analysis/blocks.m
>    cfe/trunk/test/Analysis/inline-plist.c
>    cfe/trunk/test/Analysis/retain-release.m
> 
> Modified: cfe/trunk/include/clang/Analysis/AnalysisContext.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/AnalysisContext.h?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Analysis/AnalysisContext.h (original)
> +++ cfe/trunk/include/clang/Analysis/AnalysisContext.h Fri Jun  1 15:04:04 2012
> @@ -38,6 +38,7 @@
> class ImplicitParamDecl;
> class LocationContextManager;
> class StackFrameContext;
> +class BlockInvocationContext;
> class AnalysisDeclContextManager;
> class LocationContext;
> 
> @@ -162,6 +163,11 @@
>                                          const Stmt *S,
>                                          const CFGBlock *Blk,
>                                          unsigned Idx);
> +  
> +  const BlockInvocationContext *
> +  getBlockInvocationContext(const LocationContext *parent,
> +                            const BlockDecl *BD,
> +                            const void *ContextData);
> 
>   /// Return the specified analysis object, lazily running the analysis if
>   /// necessary.  Return NULL if the analysis could not run.
> @@ -227,8 +233,6 @@
>   }
> 
>   const StackFrameContext *getCurrentStackFrame() const;
> -  const StackFrameContext *
> -    getStackFrameForDeclContext(const DeclContext *DC) const;
> 
>   virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
> 
> @@ -307,27 +311,32 @@
> };
> 
> class BlockInvocationContext : public LocationContext {
> -  // FIXME: Add back context-sensivity (we don't want libAnalysis to know
> -  //  about MemRegion).
>   const BlockDecl *BD;
> +  
> +  // FIXME: Come up with a more type-safe way to model context-sensitivity.
> +  const void *ContextData;
> 
>   friend class LocationContextManager;
> 
>   BlockInvocationContext(AnalysisDeclContext *ctx,
>                          const LocationContext *parent,
> -                         const BlockDecl *bd)
> -    : LocationContext(Block, ctx, parent), BD(bd) {}
> +                         const BlockDecl *bd, const void *contextData)
> +    : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
> 
> public:
>   ~BlockInvocationContext() {}
> 
>   const BlockDecl *getBlockDecl() const { return BD; }
> +  
> +  const void *getContextData() const { return ContextData; }
> 
>   void Profile(llvm::FoldingSetNodeID &ID);
> 
>   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
> -                      const LocationContext *parent, const BlockDecl *bd) {
> +                      const LocationContext *parent, const BlockDecl *bd,
> +                      const void *contextData) {
>     ProfileCommon(ID, Block, ctx, parent, bd);
> +    ID.AddPointer(contextData);
>   }
> 
>   static bool classof(const LocationContext *Ctx) {
> @@ -348,6 +357,12 @@
>   const ScopeContext *getScope(AnalysisDeclContext *ctx,
>                                const LocationContext *parent,
>                                const Stmt *s);
> +  
> +  const BlockInvocationContext *
> +  getBlockInvocationContext(AnalysisDeclContext *ctx,
> +                            const LocationContext *parent,
> +                            const BlockDecl *BD,
> +                            const void *ContextData);
> 
>   /// Discard all previously created LocationContext objects.
>   void clear();
> @@ -404,7 +419,6 @@
>     return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
>   }
> 
> -
>   /// Discard all previously created AnalysisDeclContexts.
>   void clear();
> 
> 
> Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
> +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Fri Jun  1 15:04:04 2012
> @@ -494,7 +494,7 @@
>                     ProgramStateRef St, SVal location,
>                     const ProgramPointTag *tag, bool isLoad);
> 
> -  bool shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred);
> +  bool shouldInlineDecl(const Decl *D, ExplodedNode *Pred);
>   bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);
> 
>   bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
> 
> Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h (original)
> +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h Fri Jun  1 15:04:04 2012
> @@ -572,7 +572,7 @@
> 
>   RegionSetTy RegionRoots;
> 
> -  const LocationContext *LCtx;
> +  const StackFrameContext *LCtx;
>   const Stmt *Loc;
>   SymbolManager& SymMgr;
>   StoreRef reapedStore;
> @@ -586,7 +586,8 @@
>   /// considered live.
>   SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr,
>                StoreManager &storeMgr)
> -   : LCtx(ctx), Loc(s), SymMgr(symmgr), reapedStore(0, storeMgr) {}
> +   : LCtx(ctx->getCurrentStackFrame()), Loc(s), SymMgr(symmgr),
> +     reapedStore(0, storeMgr) {}
> 
>   ~SymbolReaper() {}
> 
> 
> Modified: cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp (original)
> +++ cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp Fri Jun  1 15:04:04 2012
> @@ -204,6 +204,14 @@
>   return getLocationContextManager().getStackFrame(this, Parent, S, Blk, Idx);
> }
> 
> +const BlockInvocationContext *
> +AnalysisDeclContext::getBlockInvocationContext(const LocationContext *parent,
> +                                               const clang::BlockDecl *BD,
> +                                               const void *ContextData) {
> +  return getLocationContextManager().getBlockInvocationContext(this, parent,
> +                                                               BD, ContextData);
> +}
> +
> LocationContextManager & AnalysisDeclContext::getLocationContextManager() {
>   assert(Manager &&
>          "Cannot create LocationContexts without an AnalysisDeclContextManager!");
> @@ -234,7 +242,7 @@
> }
> 
> void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
> -  Profile(ID, getAnalysisDeclContext(), getParent(), BD);
> +  Profile(ID, getAnalysisDeclContext(), getParent(), BD, ContextData);
> }
> 
> //===----------------------------------------------------------------------===//
> @@ -283,6 +291,24 @@
>   return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
> }
> 
> +const BlockInvocationContext *
> +LocationContextManager::getBlockInvocationContext(AnalysisDeclContext *ctx,
> +                                                  const LocationContext *parent,
> +                                                  const BlockDecl *BD,
> +                                                  const void *ContextData) {
> +  llvm::FoldingSetNodeID ID;
> +  BlockInvocationContext::Profile(ID, ctx, parent, BD, ContextData);
> +  void *InsertPos;
> +  BlockInvocationContext *L =
> +    cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
> +                                                                    InsertPos));
> +  if (!L) {
> +    L = new BlockInvocationContext(ctx, parent, BD, ContextData);
> +    Contexts.InsertNode(L, InsertPos);
> +  }
> +  return L;
> +}
> +
> //===----------------------------------------------------------------------===//
> // LocationContext methods.
> //===----------------------------------------------------------------------===//
> @@ -297,19 +323,6 @@
>   return NULL;
> }
> 
> -const StackFrameContext *
> -LocationContext::getStackFrameForDeclContext(const DeclContext *DC) const {
> -  const LocationContext *LC = this;
> -  while (LC) {
> -    if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) {
> -      if (cast<DeclContext>(SFC->getDecl()) == DC)
> -        return SFC;
> -    }
> -    LC = LC->getParent();
> -  }
> -  return NULL;
> -}
> -
> bool LocationContext::isParentOf(const LocationContext *LC) const {
>   do {
>     const LocationContext *Parent = LC->getParent();
> 
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Fri Jun  1 15:04:04 2012
> @@ -103,7 +103,12 @@
> 
>   const StackFrameContext *calleeCtx =
>       CEBNode->getLocationContext()->getCurrentStackFrame();
> -  const LocationContext *callerCtx = calleeCtx->getParent();
> +  
> +  // The parent context might not be a stack frame, so make sure we
> +  // look up the first enclosing stack frame.
> +  const StackFrameContext *callerCtx =
> +    calleeCtx->getParent()->getCurrentStackFrame();
> +  
>   const Stmt *CE = calleeCtx->getCallSite();
>   ProgramStateRef state = CEBNode->getState();
>   // Find the last statement in the function and the corresponding basic block.
> @@ -199,8 +204,8 @@
> }
> 
> // Determine if we should inline the call.
> -bool ExprEngine::shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred) {
> -  AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD);
> +bool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) {
> +  AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D);
>   const CFG *CalleeCFG = CalleeADC->getCFG();
> 
>   // It is possible that the CFG cannot be constructed.
> @@ -212,7 +217,7 @@
>         == AMgr.InlineMaxStackDepth)
>     return false;
> 
> -  if (Engine.FunctionSummaries->hasReachedMaxBlockCount(FD))
> +  if (Engine.FunctionSummaries->hasReachedMaxBlockCount(D))
>     return false;
> 
>   if (CalleeCFG->getNumBlockIDs() > AMgr.InlineMaxFunctionSize)
> @@ -231,10 +236,7 @@
>   if (const PointerType *PT = callee->getAs<PointerType>())
>     FT = dyn_cast<FunctionProtoType>(PT->getPointeeType());
>   else if (const BlockPointerType *BT = callee->getAs<BlockPointerType>()) {
> -    // FIXME: inline blocks.
> -    // FT = dyn_cast<FunctionProtoType>(BT->getPointeeType());
> -    (void) BT;
> -    return false;
> +    FT = dyn_cast<FunctionProtoType>(BT->getPointeeType());
>   }
>   // If we have no prototype, assume the function is okay.
>   if (!FT)
> @@ -250,41 +252,64 @@
>   if (!shouldInlineCallExpr(CE, this))
>     return false;
> 
> +  const StackFrameContext *CallerSFC =
> +    Pred->getLocationContext()->getCurrentStackFrame();
> +
>   ProgramStateRef state = Pred->getState();
>   const Expr *Callee = CE->getCallee();
> -  const FunctionDecl *FD =
> -    state->getSVal(Callee, Pred->getLocationContext()).getAsFunctionDecl();
> -  if (!FD || !FD->hasBody(FD))
> -    return false;
> +  SVal CalleeVal = state->getSVal(Callee, Pred->getLocationContext());
> +  const Decl *D = 0;
> +  const LocationContext *ParentOfCallee = 0;
> +  
> +  if (const FunctionDecl *FD = CalleeVal.getAsFunctionDecl()) {
> +    if (!FD->hasBody(FD))
> +      return false;
> 
> -  switch (CE->getStmtClass()) {
> -    default:
> -      // FIXME: Handle C++.
> -      break;
> -    case Stmt::CallExprClass: {
> -      if (!shouldInlineDecl(FD, Pred))
> -        return false;
> -
> -      // Construct a new stack frame for the callee.
> -      AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD);
> -      const StackFrameContext *CallerSFC =
> -      Pred->getLocationContext()->getCurrentStackFrame();
> -      const StackFrameContext *CalleeSFC =
> -      CalleeADC->getStackFrame(CallerSFC, CE,
> -                               currentBuilderContext->getBlock(),
> -                               currentStmtIdx);
> -      
> -      CallEnter Loc(CE, CalleeSFC, Pred->getLocationContext());
> -      bool isNew;
> -      if (ExplodedNode *N = G.getNode(Loc, state, false, &isNew)) {
> -        N->addPredecessor(Pred, G);
> -        if (isNew)
> -          Engine.getWorkList()->enqueue(N);
> +    switch (CE->getStmtClass()) {
> +      default:
> +        // FIXME: Handle C++.
> +        break;
> +      case Stmt::CallExprClass: {
> +        D = FD;
> +        break;
> +        
>       }
> -      return true;
>     }
> +  } else if (const BlockDataRegion *BR =
> +              dyn_cast_or_null<BlockDataRegion>(CalleeVal.getAsRegion())) {
> +    assert(CE->getStmtClass() == Stmt::CallExprClass);
> +    const BlockDecl *BD = BR->getDecl();
> +    D = BD;
> +    AnalysisDeclContext *BlockCtx = AMgr.getAnalysisDeclContext(BD);
> +    ParentOfCallee = BlockCtx->getBlockInvocationContext(CallerSFC,
> +                                                         BD,
> +                                                         BR);
> +  } else {
> +    // This is case we don't handle yet.
> +    return false;
>   }
> -  return false;
> +  
> +  if (!D || !shouldInlineDecl(D, Pred))
> +    return false;
> +  
> +  if (!ParentOfCallee)
> +    ParentOfCallee = CallerSFC;
> +
> +  // Construct a new stack frame for the callee.
> +  AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D);
> +  const StackFrameContext *CalleeSFC =
> +    CalleeADC->getStackFrame(ParentOfCallee, CE,
> +                             currentBuilderContext->getBlock(),
> +                             currentStmtIdx);
> +  
> +  CallEnter Loc(CE, CalleeSFC, Pred->getLocationContext());
> +  bool isNew;
> +  if (ExplodedNode *N = G.getNode(Loc, state, false, &isNew)) {
> +    N->addPredecessor(Pred, G);
> +    if (isNew)
> +      Engine.getWorkList()->enqueue(N);
> +  }
> +  return true;
> }
> 
> static bool isPointerToConst(const ParmVarDecl *ParamDecl) {
> 
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp Fri Jun  1 15:04:04 2012
> @@ -643,6 +643,37 @@
>   return getSubRegion<ObjCStringRegion>(Str, getGlobalsRegion());
> }
> 
> +/// Look through a chain of LocationContexts to either find the
> +/// StackFrameContext that matches a DeclContext, or find a VarRegion
> +/// for a variable captured by a block.
> +static llvm::PointerUnion<const StackFrameContext *, const VarRegion *>
> +getStackOrCaptureRegionForDeclContext(const LocationContext *LC,
> +                                      const DeclContext *DC,
> +                                      const VarDecl *VD) {
> +  while (LC) {
> +    if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) {
> +      if (cast<DeclContext>(SFC->getDecl()) == DC)
> +        return SFC;
> +    }
> +    if (const BlockInvocationContext *BC =
> +        dyn_cast<BlockInvocationContext>(LC)) {
> +      const BlockDataRegion *BR =
> +        static_cast<const BlockDataRegion*>(BC->getContextData());
> +      // FIXME: This can be made more efficient.
> +      for (BlockDataRegion::referenced_vars_iterator
> +           I = BR->referenced_vars_begin(),
> +           E = BR->referenced_vars_end(); I != E; ++I) {
> +        if (const VarRegion *VR = dyn_cast<VarRegion>(I.getOriginalRegion()))
> +          if (VR->getDecl() == VD)
> +            return cast<VarRegion>(I.getCapturedRegion());
> +      }
> +    }
> +    
> +    LC = LC->getParent();
> +  }
> +  return (const StackFrameContext*)0;
> +}
> +
> const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
>                                                 const LocationContext *LC) {
>   const MemRegion *sReg = 0;
> @@ -675,7 +706,13 @@
>     // FIXME: Once we implement scope handling, we will need to properly lookup
>     // 'D' to the proper LocationContext.
>     const DeclContext *DC = D->getDeclContext();
> -    const StackFrameContext *STC = LC->getStackFrameForDeclContext(DC);
> +    llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V =
> +      getStackOrCaptureRegionForDeclContext(LC, DC, D);
> +    
> +    if (V.is<const VarRegion*>())
> +      return V.get<const VarRegion*>();
> +    
> +    const StackFrameContext *STC = V.get<const StackFrameContext*>();
> 
>     if (!STC)
>       sReg = getUnknownRegion();
> 
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Fri Jun  1 15:04:04 2012
> @@ -568,6 +568,16 @@
>     if (!scan(SR->getSuperRegion()))
>       return false;
> 
> +  // Regions captured by a block are also implicitly reachable.
> +  if (const BlockDataRegion *BDR = dyn_cast<BlockDataRegion>(R)) {
> +    BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(),
> +                                              E = BDR->referenced_vars_end();
> +    for ( ; I != E; ++I) {
> +      if (!scan(I.getCapturedRegion()))
> +        return false;
> +    }
> +  }
> +
>   // Now look at the binding to this region (if any).
>   if (!scan(state->getSValAsScalarOrLoc(R)))
>     return false;
> 
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Fri Jun  1 15:04:04 2012
> @@ -394,6 +394,12 @@
>                            const LocationContext *callerCtx,
>                            const StackFrameContext *calleeCtx);
> 
> +  StoreRef enterStackFrame(ProgramStateRef state,
> +                           const FunctionDecl *FD,
> +                           const LocationContext *callerCtx,
> +                           const StackFrameContext *calleeCtx);
> +
> +  
>   //===------------------------------------------------------------------===//
>   // Region "extents".
>   //===------------------------------------------------------------------===//
> @@ -1944,8 +1950,18 @@
>   }
> 
>   // If V is a region, then add it to the worklist.
> -  if (const MemRegion *R = V.getAsRegion())
> +  if (const MemRegion *R = V.getAsRegion()) {
>     AddToWorkList(R);
> +    
> +    // All regions captured by a block are also live.
> +    if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
> +      BlockDataRegion::referenced_vars_iterator I = BR->referenced_vars_begin(),
> +                                                E = BR->referenced_vars_end();
> +        for ( ; I != E; ++I)
> +          AddToWorkList(I.getCapturedRegion());
> +    }
> +  }
> +    
> 
>   // Update the set of live symbols.
>   for (SymExpr::symbol_iterator SI = V.symbol_begin(), SE = V.symbol_end();
> @@ -1964,21 +1980,6 @@
>     // should continue to track that symbol.
>     if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
>       SymReaper.markLive(SymR->getSymbol());
> -
> -    // For BlockDataRegions, enqueue the VarRegions for variables marked
> -    // with __block (passed-by-reference).
> -    // via BlockDeclRefExprs.
> -    if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(R)) {
> -      for (BlockDataRegion::referenced_vars_iterator
> -           RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end();
> -           RI != RE; ++RI) {
> -        if ((*RI)->getDecl()->getAttr<BlocksAttr>())
> -          AddToWorkList(*RI);
> -      }
> -
> -      // No possible data bindings on a BlockDataRegion.
> -      return;
> -    }
>   }
> 
>   // Visit the data binding for K.
> @@ -2045,12 +2046,37 @@
>   return StoreRef(B.getRootWithoutRetain(), *this);
> }
> 
> +StoreRef RegionStoreManager::enterStackFrame(ProgramStateRef state,
> +                                             const LocationContext *callerCtx,
> +                                             const StackFrameContext *calleeCtx)
> +{
> +  const Decl *D = calleeCtx->getDecl();
> +  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
> +    return enterStackFrame(state, FD, callerCtx, calleeCtx);
> +  
> +  // FIXME: when we handle more cases, this will need to be expanded.
> +  
> +  const BlockDecl *BD = cast<BlockDecl>(D);
> +  BlockDecl::param_const_iterator PI = BD->param_begin(),
> +                                  PE = BD->param_end();
> +  StoreRef store = StoreRef(state->getStore(), *this);
> +  const CallExpr *CE = cast<CallExpr>(calleeCtx->getCallSite());
> +  CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
> +  for (; AI != AE && PI != PE; ++AI, ++PI) {
> +    SVal ArgVal = state->getSVal(*AI, callerCtx);
> +    store = Bind(store.getStore(),
> +                 svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)),
> +                 ArgVal);
> +  }
> +  
> +  return store;
> +}
> 
> StoreRef RegionStoreManager::enterStackFrame(ProgramStateRef state,
> +                                             const FunctionDecl *FD,
>                                              const LocationContext *callerCtx,
>                                              const StackFrameContext *calleeCtx)
> {
> -  FunctionDecl const *FD = cast<FunctionDecl>(calleeCtx->getDecl());
>   FunctionDecl::param_const_iterator PI = FD->param_begin(), 
>                                      PE = FD->param_end();
>   StoreRef store = StoreRef(state->getStore(), *this);
> 
> Modified: cfe/trunk/test/Analysis/blocks.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/blocks.m?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/test/Analysis/blocks.m (original)
> +++ cfe/trunk/test/Analysis/blocks.m Fri Jun  1 15:04:04 2012
> @@ -79,9 +79,7 @@
> void test2_b() {
>   static int y = 0;
>   __block int x;
> -  // This is also a bug, but should be found not by checking the value
> -  // 'x' is bound at block creation.
> -  ^{ y = x + 1; }(); // no-warning
> +  ^{ y = x + 1; }(); // expected-warning {{left operand of '+' is a garbage value}}
> }
> 
> void test2_c() {
> 
> Modified: cfe/trunk/test/Analysis/inline-plist.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inline-plist.c?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/test/Analysis/inline-plist.c (original)
> +++ cfe/trunk/test/Analysis/inline-plist.c Fri Jun  1 15:04:04 2012
> @@ -1,4 +1,4 @@
> -// RUN: %clang --analyze %s -Xclang -analyzer-ipa=inlining -o %t
> +// RUN: %clang --analyze %s -Xclang -analyzer-ipa=inlining -fblocks -o %t
> // RUN: FileCheck -input-file %t %s
> 
> // <rdar://problem/10967815>
> @@ -37,6 +37,32 @@
>     triggers_bug(p);
> }
> 
> +// ========================================================================== //
> +// Test inlining of blocks.
> +// ========================================================================== //
> +
> +void test_block__capture_null() {
> +  int *p = 0;
> +  ^(){ *p = 1; }();
> +}
> +
> +void test_block_ret() {
> +  int *p = ^(){ int *q = 0; return q; }();
> +  *p = 1;
> +}
> +
> +void test_block_blockvar() {
> +  __block int *p;
> +  ^(){ p = 0; }();
> +  *p = 1;
> +}
> +
> +void test_block_arg() {
> +  int *p;
> +  ^(int **q){ *q = 0; }(&p);
> +  *p = 1;
> +}
> +
> // CHECK: <?xml version="1.0" encoding="UTF-8"?>
> // CHECK: <plist version="1.0">
> // CHECK: <dict>
> @@ -630,6 +656,528 @@
> // CHECK:    <key>file</key><integer>0</integer>
> // CHECK:   </dict>
> // CHECK:   </dict>
> +// CHECK:   <dict>
> +// CHECK:    <key>path</key>
> +// CHECK:    <array>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>event</string>
> +// CHECK:      <key>location</key>
> +// CHECK:      <dict>
> +// CHECK:       <key>line</key><integer>45</integer>
> +// CHECK:       <key>col</key><integer>3</integer>
> +// CHECK:       <key>file</key><integer>0</integer>
> +// CHECK:      </dict>
> +// CHECK:      <key>ranges</key>
> +// CHECK:      <array>
> +// CHECK:        <array>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>45</integer>
> +// CHECK:          <key>col</key><integer>3</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>45</integer>
> +// CHECK:          <key>col</key><integer>8</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:        </array>
> +// CHECK:      </array>
> +// CHECK:      <key>depth</key><integer>0</integer>
> +// CHECK:      <key>extended_message</key>
> +// CHECK:      <string>Variable 'p' initialized to a null pointer value</string>
> +// CHECK:      <key>message</key>
> +// CHECK: <string>Variable 'p' initialized to a null pointer value</string>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>control</string>
> +// CHECK:      <key>edges</key>
> +// CHECK:       <array>
> +// CHECK:        <dict>
> +// CHECK:         <key>start</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>45</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>45</integer>
> +// CHECK:            <key>col</key><integer>8</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:         <key>end</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>46</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>46</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:        </dict>
> +// CHECK:       </array>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>event</string>
> +// CHECK:      <key>location</key>
> +// CHECK:      <dict>
> +// CHECK:       <key>line</key><integer>46</integer>
> +// CHECK:       <key>col</key><integer>3</integer>
> +// CHECK:       <key>file</key><integer>0</integer>
> +// CHECK:      </dict>
> +// CHECK:      <key>ranges</key>
> +// CHECK:      <array>
> +// CHECK:        <array>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>46</integer>
> +// CHECK:          <key>col</key><integer>3</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>46</integer>
> +// CHECK:          <key>col</key><integer>18</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:        </array>
> +// CHECK:      </array>
> +// CHECK:      <key>depth</key><integer>0</integer>
> +// CHECK:      <key>extended_message</key>
> +// CHECK:      <string>Calling anonymous block</string>
> +// CHECK:      <key>message</key>
> +// CHECK: <string>Calling anonymous block</string>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>event</string>
> +// CHECK:      <key>location</key>
> +// CHECK:      <dict>
> +// CHECK:       <key>line</key><integer>46</integer>
> +// CHECK:       <key>col</key><integer>3</integer>
> +// CHECK:       <key>file</key><integer>0</integer>
> +// CHECK:      </dict>
> +// CHECK:      <key>depth</key><integer>1</integer>
> +// CHECK:      <key>extended_message</key>
> +// CHECK:      <string>Entered call from 'test_block__capture_null'</string>
> +// CHECK:      <key>message</key>
> +// CHECK: <string>Entered call from 'test_block__capture_null'</string>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>control</string>
> +// CHECK:      <key>edges</key>
> +// CHECK:       <array>
> +// CHECK:        <dict>
> +// CHECK:         <key>start</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>46</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>46</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:         <key>end</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>46</integer>
> +// CHECK:            <key>col</key><integer>8</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>46</integer>
> +// CHECK:            <key>col</key><integer>8</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:        </dict>
> +// CHECK:       </array>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>event</string>
> +// CHECK:      <key>location</key>
> +// CHECK:      <dict>
> +// CHECK:       <key>line</key><integer>46</integer>
> +// CHECK:       <key>col</key><integer>8</integer>
> +// CHECK:       <key>file</key><integer>0</integer>
> +// CHECK:      </dict>
> +// CHECK:      <key>ranges</key>
> +// CHECK:      <array>
> +// CHECK:        <array>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>46</integer>
> +// CHECK:          <key>col</key><integer>9</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>46</integer>
> +// CHECK:          <key>col</key><integer>9</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:        </array>
> +// CHECK:      </array>
> +// CHECK:      <key>depth</key><integer>1</integer>
> +// CHECK:      <key>extended_message</key>
> +// CHECK:      <string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:      <key>message</key>
> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:     </dict>
> +// CHECK:    </array>
> +// CHECK:    <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:    <key>category</key><string>Logic error</string>
> +// CHECK:    <key>type</key><string>Dereference of null pointer</string>
> +// CHECK:   <key>location</key>
> +// CHECK:   <dict>
> +// CHECK:    <key>line</key><integer>46</integer>
> +// CHECK:    <key>col</key><integer>8</integer>
> +// CHECK:    <key>file</key><integer>0</integer>
> +// CHECK:   </dict>
> +// CHECK:   </dict>
> +// CHECK:   <dict>
> +// CHECK:    <key>path</key>
> +// CHECK:    <array>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>control</string>
> +// CHECK:      <key>edges</key>
> +// CHECK:       <array>
> +// CHECK:        <dict>
> +// CHECK:         <key>start</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>50</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>50</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:         <key>end</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>50</integer>
> +// CHECK:            <key>col</key><integer>12</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>50</integer>
> +// CHECK:            <key>col</key><integer>12</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:        </dict>
> +// CHECK:       </array>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>control</string>
> +// CHECK:      <key>edges</key>
> +// CHECK:       <array>
> +// CHECK:        <dict>
> +// CHECK:         <key>start</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>50</integer>
> +// CHECK:            <key>col</key><integer>12</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>50</integer>
> +// CHECK:            <key>col</key><integer>41</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:         <key>end</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>51</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>51</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:        </dict>
> +// CHECK:       </array>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>event</string>
> +// CHECK:      <key>location</key>
> +// CHECK:      <dict>
> +// CHECK:       <key>line</key><integer>51</integer>
> +// CHECK:       <key>col</key><integer>3</integer>
> +// CHECK:       <key>file</key><integer>0</integer>
> +// CHECK:      </dict>
> +// CHECK:      <key>ranges</key>
> +// CHECK:      <array>
> +// CHECK:        <array>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>51</integer>
> +// CHECK:          <key>col</key><integer>4</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>51</integer>
> +// CHECK:          <key>col</key><integer>4</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:        </array>
> +// CHECK:      </array>
> +// CHECK:      <key>depth</key><integer>0</integer>
> +// CHECK:      <key>extended_message</key>
> +// CHECK:      <string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:      <key>message</key>
> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:     </dict>
> +// CHECK:    </array>
> +// CHECK:    <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:    <key>category</key><string>Logic error</string>
> +// CHECK:    <key>type</key><string>Dereference of null pointer</string>
> +// CHECK:   <key>issue_context_kind</key><string>function</string>
> +// CHECK:   <key>issue_context</key><string>test_block_ret</string>
> +// CHECK:   <key>location</key>
> +// CHECK:   <dict>
> +// CHECK:    <key>line</key><integer>51</integer>
> +// CHECK:    <key>col</key><integer>3</integer>
> +// CHECK:    <key>file</key><integer>0</integer>
> +// CHECK:   </dict>
> +// CHECK:   </dict>
> +// CHECK:   <dict>
> +// CHECK:    <key>path</key>
> +// CHECK:    <array>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>control</string>
> +// CHECK:      <key>edges</key>
> +// CHECK:       <array>
> +// CHECK:        <dict>
> +// CHECK:         <key>start</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>55</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>55</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:         <key>end</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>56</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>56</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:        </dict>
> +// CHECK:       </array>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>control</string>
> +// CHECK:      <key>edges</key>
> +// CHECK:       <array>
> +// CHECK:        <dict>
> +// CHECK:         <key>start</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>56</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>56</integer>
> +// CHECK:            <key>col</key><integer>17</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:         <key>end</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>57</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>57</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:        </dict>
> +// CHECK:       </array>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>event</string>
> +// CHECK:      <key>location</key>
> +// CHECK:      <dict>
> +// CHECK:       <key>line</key><integer>57</integer>
> +// CHECK:       <key>col</key><integer>3</integer>
> +// CHECK:       <key>file</key><integer>0</integer>
> +// CHECK:      </dict>
> +// CHECK:      <key>ranges</key>
> +// CHECK:      <array>
> +// CHECK:        <array>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>57</integer>
> +// CHECK:          <key>col</key><integer>4</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>57</integer>
> +// CHECK:          <key>col</key><integer>4</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:        </array>
> +// CHECK:      </array>
> +// CHECK:      <key>depth</key><integer>0</integer>
> +// CHECK:      <key>extended_message</key>
> +// CHECK:      <string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:      <key>message</key>
> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:     </dict>
> +// CHECK:    </array>
> +// CHECK:    <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:    <key>category</key><string>Logic error</string>
> +// CHECK:    <key>type</key><string>Dereference of null pointer</string>
> +// CHECK:   <key>issue_context_kind</key><string>function</string>
> +// CHECK:   <key>issue_context</key><string>test_block_blockvar</string>
> +// CHECK:   <key>location</key>
> +// CHECK:   <dict>
> +// CHECK:    <key>line</key><integer>57</integer>
> +// CHECK:    <key>col</key><integer>3</integer>
> +// CHECK:    <key>file</key><integer>0</integer>
> +// CHECK:   </dict>
> +// CHECK:   </dict>
> +// CHECK:   <dict>
> +// CHECK:    <key>path</key>
> +// CHECK:    <array>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>control</string>
> +// CHECK:      <key>edges</key>
> +// CHECK:       <array>
> +// CHECK:        <dict>
> +// CHECK:         <key>start</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>61</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>61</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:         <key>end</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>62</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>62</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:        </dict>
> +// CHECK:       </array>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>control</string>
> +// CHECK:      <key>edges</key>
> +// CHECK:       <array>
> +// CHECK:        <dict>
> +// CHECK:         <key>start</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>62</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>62</integer>
> +// CHECK:            <key>col</key><integer>27</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:         <key>end</key>
> +// CHECK:          <array>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>63</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:           <dict>
> +// CHECK:            <key>line</key><integer>63</integer>
> +// CHECK:            <key>col</key><integer>3</integer>
> +// CHECK:            <key>file</key><integer>0</integer>
> +// CHECK:           </dict>
> +// CHECK:          </array>
> +// CHECK:        </dict>
> +// CHECK:       </array>
> +// CHECK:     </dict>
> +// CHECK:     <dict>
> +// CHECK:      <key>kind</key><string>event</string>
> +// CHECK:      <key>location</key>
> +// CHECK:      <dict>
> +// CHECK:       <key>line</key><integer>63</integer>
> +// CHECK:       <key>col</key><integer>3</integer>
> +// CHECK:       <key>file</key><integer>0</integer>
> +// CHECK:      </dict>
> +// CHECK:      <key>ranges</key>
> +// CHECK:      <array>
> +// CHECK:        <array>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>63</integer>
> +// CHECK:          <key>col</key><integer>4</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:         <dict>
> +// CHECK:          <key>line</key><integer>63</integer>
> +// CHECK:          <key>col</key><integer>4</integer>
> +// CHECK:          <key>file</key><integer>0</integer>
> +// CHECK:         </dict>
> +// CHECK:        </array>
> +// CHECK:      </array>
> +// CHECK:      <key>depth</key><integer>0</integer>
> +// CHECK:      <key>extended_message</key>
> +// CHECK:      <string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:      <key>message</key>
> +// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:     </dict>
> +// CHECK:    </array>
> +// CHECK:    <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</string>
> +// CHECK:    <key>category</key><string>Logic error</string>
> +// CHECK:    <key>type</key><string>Dereference of null pointer</string>
> +// CHECK:   <key>issue_context_kind</key><string>function</string>
> +// CHECK:   <key>issue_context</key><string>test_block_arg</string>
> +// CHECK:   <key>location</key>
> +// CHECK:   <dict>
> +// CHECK:    <key>line</key><integer>63</integer>
> +// CHECK:    <key>col</key><integer>3</integer>
> +// CHECK:    <key>file</key><integer>0</integer>
> +// CHECK:   </dict>
> +// CHECK:   </dict>
> // CHECK:  </array>
> // CHECK: </dict>
> // CHECK: </plist>
> 
> Modified: cfe/trunk/test/Analysis/retain-release.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.m?rev=157833&r1=157832&r2=157833&view=diff
> ==============================================================================
> --- cfe/trunk/test/Analysis/retain-release.m (original)
> +++ cfe/trunk/test/Analysis/retain-release.m Fri Jun  1 15:04:04 2012
> @@ -1452,8 +1452,7 @@
> }
> 
> void test_blocks_1_indirect_retain_via_call(void) {
> -  // Eventually this should be reported as a leak.
> -  NSNumber *number = [[NSNumber alloc] initWithInt:5]; // no-warning
> +  NSNumber *number = [[NSNumber alloc] initWithInt:5]; // expected-warning {{leak}}
>   ^(NSObject *o){ [o retain]; }(number);
> }
> 
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120601/66e42eae/attachment.html>


More information about the cfe-commits mailing list