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