[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