<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 'p' initialized to a null pointer value</string><br>+// CHECK: <key>message</key><br>+// CHECK: <string>Variable 'p' 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 'test_block__capture_null'</string><br>+// CHECK: <key>message</key><br>+// CHECK: <string>Entered call from 'test_block__capture_null'</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 'p')</string><br>+// CHECK: <key>message</key><br>+// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string><br>+// CHECK: </dict><br>+// CHECK: </array><br>+// CHECK: <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</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 'p')</string><br>+// CHECK: <key>message</key><br>+// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string><br>+// CHECK: </dict><br>+// CHECK: </array><br>+// CHECK: <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</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 'p')</string><br>+// CHECK: <key>message</key><br>+// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string><br>+// CHECK: </dict><br>+// CHECK: </array><br>+// CHECK: <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</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 'p')</string><br>+// CHECK: <key>message</key><br>+// CHECK: <string>Dereference of null pointer (loaded from variable 'p')</string><br>+// CHECK: </dict><br>+// CHECK: </array><br>+// CHECK: <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</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>