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