forked from OSchip/llvm-project
[analyzer] Malloc: drop symbols captured by blocks.
llvm-svn: 153232
This commit is contained in:
parent
f8712de58c
commit
9fe8098e29
|
@ -89,6 +89,7 @@ class MallocChecker : public Checker<check::DeadSymbols,
|
||||||
check::PreStmt<ReturnStmt>,
|
check::PreStmt<ReturnStmt>,
|
||||||
check::PreStmt<CallExpr>,
|
check::PreStmt<CallExpr>,
|
||||||
check::PostStmt<CallExpr>,
|
check::PostStmt<CallExpr>,
|
||||||
|
check::PostStmt<BlockExpr>,
|
||||||
check::Location,
|
check::Location,
|
||||||
check::Bind,
|
check::Bind,
|
||||||
eval::Assume,
|
eval::Assume,
|
||||||
|
@ -116,6 +117,7 @@ public:
|
||||||
|
|
||||||
void checkPreStmt(const CallExpr *S, CheckerContext &C) const;
|
void checkPreStmt(const CallExpr *S, CheckerContext &C) const;
|
||||||
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
|
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
|
||||||
|
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
|
||||||
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
|
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
|
||||||
void checkEndPath(CheckerContext &C) const;
|
void checkEndPath(CheckerContext &C) const;
|
||||||
void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
|
void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
|
||||||
|
@ -1008,6 +1010,46 @@ void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
|
||||||
checkEscape(Sym, E, C);
|
checkEscape(Sym, E, C);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Blocks should be either inlined or should call invalidate regions
|
||||||
|
// upon invocation. After that's in place, special casing here will not be
|
||||||
|
// needed.
|
||||||
|
void MallocChecker::checkPostStmt(const BlockExpr *BE,
|
||||||
|
CheckerContext &C) const {
|
||||||
|
|
||||||
|
// Scan the BlockDecRefExprs for any object the retain count checker
|
||||||
|
// may be tracking.
|
||||||
|
if (!BE->getBlockDecl()->hasCaptures())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ProgramStateRef state = C.getState();
|
||||||
|
const BlockDataRegion *R =
|
||||||
|
cast<BlockDataRegion>(state->getSVal(BE,
|
||||||
|
C.getLocationContext()).getAsRegion());
|
||||||
|
|
||||||
|
BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
|
||||||
|
E = R->referenced_vars_end();
|
||||||
|
|
||||||
|
if (I == E)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SmallVector<const MemRegion*, 10> Regions;
|
||||||
|
const LocationContext *LC = C.getLocationContext();
|
||||||
|
MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
|
||||||
|
|
||||||
|
for ( ; I != E; ++I) {
|
||||||
|
const VarRegion *VR = *I;
|
||||||
|
if (VR->getSuperRegion() == R) {
|
||||||
|
VR = MemMgr.getVarRegion(VR->getDecl(), LC);
|
||||||
|
}
|
||||||
|
Regions.push_back(VR);
|
||||||
|
}
|
||||||
|
|
||||||
|
state =
|
||||||
|
state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
|
||||||
|
Regions.data() + Regions.size()).getState();
|
||||||
|
C.addTransition(state);
|
||||||
|
}
|
||||||
|
|
||||||
bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
|
bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
|
||||||
const Stmt *S) const {
|
const Stmt *S) const {
|
||||||
assert(Sym);
|
assert(Sym);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify %s
|
// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -fblocks %s
|
||||||
#include "system-header-simulator-objc.h"
|
#include "system-header-simulator-objc.h"
|
||||||
|
|
||||||
typedef __typeof(sizeof(int)) size_t;
|
typedef __typeof(sizeof(int)) size_t;
|
||||||
|
@ -97,3 +97,12 @@ NSData *radar10976702() {
|
||||||
return [NSData dataWithBytesNoCopy:bytes length:10]; // no-warning
|
return [NSData dataWithBytesNoCopy:bytes length:10]; // no-warning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testBlocks() {
|
||||||
|
int *x= (int*)malloc(sizeof(int));
|
||||||
|
int (^myBlock)(int) = ^(int num) {
|
||||||
|
free(x);
|
||||||
|
return num;
|
||||||
|
};
|
||||||
|
myBlock(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue