Fix: <rdar://problem/7468209> SymbolManager::isLive() should not crash on captured block variables that are passed by reference

llvm-svn: 91348
This commit is contained in:
Ted Kremenek 2009-12-14 22:15:06 +00:00
parent 590d18f103
commit 814c416636
6 changed files with 40 additions and 5 deletions

View File

@ -621,6 +621,8 @@ class VarRegion : public DeclRegion {
public:
const VarDecl *getDecl() const { return cast<VarDecl>(D); }
const StackFrameContext *getStackFrame() const;
QualType getValueType(ASTContext& C) const {
// FIXME: We can cache this if needed.
return C.getCanonicalType(getDecl()->getType());

View File

@ -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() {}

View File

@ -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();

View File

@ -165,6 +165,15 @@ MemRegionManager* SubRegion::getMemRegionManager() const {
} while (1);
}
const StackFrameContext *VarRegion::getStackFrame() const {
const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
return SSR ? SSR->getStackFrame() : NULL;
}
//===----------------------------------------------------------------------===//
// FoldingSet profiling.
//===----------------------------------------------------------------------===//
void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned)getKind());
}

View File

@ -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() {}

View File

@ -618,3 +618,21 @@ typedef void (^RDar_7462324_Callback)(id obj);
}
@end
//===----------------------------------------------------------------------===//
// <rdar://problem/7468209> - 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();
}();
}