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