From 814c416636780d2d3a76bdc1a9e0a301d2251888 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Mon, 14 Dec 2009 22:15:06 +0000 Subject: [PATCH] Fix: SymbolManager::isLive() should not crash on captured block variables that are passed by reference llvm-svn: 91348 --- .../clang/Analysis/PathSensitive/MemRegion.h | 2 ++ .../Analysis/PathSensitive/SymbolManager.h | 8 ++++++-- clang/lib/Analysis/GRExprEngine.cpp | 5 +++-- clang/lib/Analysis/MemRegion.cpp | 9 +++++++++ clang/lib/Analysis/SymbolManager.cpp | 3 ++- clang/test/Analysis/misc-ps-region-store.m | 18 ++++++++++++++++++ 6 files changed, 40 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Analysis/PathSensitive/MemRegion.h b/clang/include/clang/Analysis/PathSensitive/MemRegion.h index 45dab1ec8421..2fe5ea0cf3ab 100644 --- a/clang/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/clang/include/clang/Analysis/PathSensitive/MemRegion.h @@ -621,6 +621,8 @@ class VarRegion : public DeclRegion { public: const VarDecl *getDecl() const { return cast(D); } + const StackFrameContext *getStackFrame() const; + QualType getValueType(ASTContext& C) const { // FIXME: We can cache this if needed. return C.getCanonicalType(getDecl()->getType()); diff --git a/clang/include/clang/Analysis/PathSensitive/SymbolManager.h b/clang/include/clang/Analysis/PathSensitive/SymbolManager.h index 8dbbaace4f49..8eb319647953 100644 --- a/clang/include/clang/Analysis/PathSensitive/SymbolManager.h +++ b/clang/include/clang/Analysis/PathSensitive/SymbolManager.h @@ -33,6 +33,7 @@ namespace clang { class MemRegion; class TypedRegion; class VarRegion; + class StackFrameContext; } namespace clang { @@ -333,10 +334,13 @@ class SymbolReaper { SetTy TheDead; LiveVariables& Liveness; SymbolManager& SymMgr; + const StackFrameContext *CurrentStackFrame; public: - SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr) - : Liveness(liveness), SymMgr(symmgr) {} + SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr, + const StackFrameContext *currentStackFrame) + : Liveness(liveness), SymMgr(symmgr), CurrentStackFrame(currentStackFrame) + {} ~SymbolReaper() {} diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index 4e88f18d0c02..033d105a9355 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -394,8 +394,9 @@ void GRExprEngine::ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder) { Builder->setAuditor(BatchAuditor.get()); // Create the cleaned state. - SymbolReaper SymReaper(Builder->getBasePredecessor()->getLiveVariables(), - SymMgr); + const ExplodedNode *BasePred = Builder->getBasePredecessor(); + SymbolReaper SymReaper(BasePred->getLiveVariables(), SymMgr, + BasePred->getLocationContext()->getCurrentStackFrame()); CleanedState = AMgr.shouldPurgeDead() ? StateMgr.RemoveDeadBindings(EntryNode->getState(), CurrentStmt, SymReaper) : EntryNode->getState(); diff --git a/clang/lib/Analysis/MemRegion.cpp b/clang/lib/Analysis/MemRegion.cpp index da45c4dfee06..bc3a5b704552 100644 --- a/clang/lib/Analysis/MemRegion.cpp +++ b/clang/lib/Analysis/MemRegion.cpp @@ -165,6 +165,15 @@ MemRegionManager* SubRegion::getMemRegionManager() const { } while (1); } +const StackFrameContext *VarRegion::getStackFrame() const { + const StackSpaceRegion *SSR = dyn_cast(getMemorySpace()); + return SSR ? SSR->getStackFrame() : NULL; +} + +//===----------------------------------------------------------------------===// +// FoldingSet profiling. +//===----------------------------------------------------------------------===// + void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger((unsigned)getKind()); } diff --git a/clang/lib/Analysis/SymbolManager.cpp b/clang/lib/Analysis/SymbolManager.cpp index da91f55bc089..3fe36b064e3d 100644 --- a/clang/lib/Analysis/SymbolManager.cpp +++ b/clang/lib/Analysis/SymbolManager.cpp @@ -221,7 +221,8 @@ bool SymbolReaper::isLive(SymbolRef sym) { } bool SymbolReaper::isLive(const Stmt *Loc, const VarRegion *VR) const { - return Liveness.isLive(Loc, VR->getDecl()); + const StackFrameContext *SFC = VR->getStackFrame(); + return SFC == CurrentStackFrame ? Liveness.isLive(Loc, VR->getDecl()) : true; } SymbolVisitor::~SymbolVisitor() {} diff --git a/clang/test/Analysis/misc-ps-region-store.m b/clang/test/Analysis/misc-ps-region-store.m index d1906778e248..e736e0f37cdb 100644 --- a/clang/test/Analysis/misc-ps-region-store.m +++ b/clang/test/Analysis/misc-ps-region-store.m @@ -618,3 +618,21 @@ typedef void (^RDar_7462324_Callback)(id obj); } @end +//===----------------------------------------------------------------------===// +// - Scanning for live variables within a block should +// not crash on variables passed by reference via __block. +//===----------------------------------------------------------------------===// + +int rdar7468209_aux(); +void rdar7468209_aux2(); + +void rdar7468209() { + __block int x = 0; + ^{ + x = rdar7468209_aux(); + // We need a second statement so that 'x' would be removed from the store if it wasn't + // passed by reference. + rdar7468209_aux_2(); + }(); +} +