зеркало из https://github.com/microsoft/clang-1.git
Do a better job at computing dead symbols.
Implemented support for better localized leaks in the CF reference count checker. Now leaks should be flagged close to where they occur. This should implement the desired functionality in <rdar://problem/5879592>, although the diagnostics still need to be improved. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50241 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
652adc6c5d
Коммит
910e999c19
|
@ -93,7 +93,8 @@ public:
|
|||
virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
|
||||
GRExprEngine& Engine,
|
||||
GRStmtNodeBuilder<ValueState>& Builder,
|
||||
ProgramPoint P, ExplodedNode<ValueState>* Pred,
|
||||
ExplodedNode<ValueState>* Pred,
|
||||
Stmt* S,
|
||||
ValueState* St,
|
||||
const ValueStateManager::DeadSymbolsTy& Dead) {}
|
||||
|
||||
|
|
|
@ -144,14 +144,16 @@ MakeReportGraph(ExplodedGraph<ValueState>* G, ExplodedNode<ValueState>* N) {
|
|||
|
||||
llvm::OwningPtr<ExplodedGraph<ValueState> > GTrim(G->Trim(&N, &N+1));
|
||||
|
||||
// Find the sink node in the trimmed graph.
|
||||
// Find the error node in the trimmed graph.
|
||||
|
||||
N = NULL;
|
||||
ExplodedNode<ValueState>* NOld = N;
|
||||
N = 0;
|
||||
|
||||
for (ExplodedGraph<ValueState>::node_iterator
|
||||
I = GTrim->nodes_begin(), E = GTrim->nodes_end(); I != E; ++I) {
|
||||
|
||||
if (I->isSink()) {
|
||||
if (I->getState() == NOld->getState() &&
|
||||
I->getLocation() == NOld->getLocation()) {
|
||||
N = &*I;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -687,10 +687,10 @@ public:
|
|||
virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
|
||||
GRExprEngine& Engine,
|
||||
GRStmtNodeBuilder<ValueState>& Builder,
|
||||
ProgramPoint P, ExplodedNode<ValueState>* Pred,
|
||||
ExplodedNode<ValueState>* Pred,
|
||||
Stmt* S,
|
||||
ValueState* St,
|
||||
const ValueStateManager::DeadSymbolsTy& Dead);
|
||||
|
||||
// Return statements.
|
||||
|
||||
virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
|
||||
|
@ -1096,21 +1096,11 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
|
|||
void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
|
||||
GRExprEngine& Eng,
|
||||
GRStmtNodeBuilder<ValueState>& Builder,
|
||||
ProgramPoint P, ExplodedNode<ValueState>* Pred,
|
||||
ExplodedNode<ValueState>* Pred,
|
||||
Stmt* S,
|
||||
ValueState* St,
|
||||
const ValueStateManager::DeadSymbolsTy& Dead) {
|
||||
|
||||
// FIXME: Have GRStmtNodeBuilder handle the case where 'P' is not PostStmt;
|
||||
// This won't result in missed leaks; we'll just flag these ones at the
|
||||
// end-of-path.
|
||||
|
||||
Stmt* S = NULL;
|
||||
|
||||
if (!isa<PostStmt>(P))
|
||||
return;
|
||||
|
||||
S = cast<PostStmt>(P).getStmt();
|
||||
|
||||
|
||||
// FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
|
||||
|
||||
RefBindings B = GetRefBindings(*St);
|
||||
|
|
|
@ -199,8 +199,8 @@ void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
|
|||
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
||||
SaveOr OldHasGen(Builder->HasGeneratedNode);
|
||||
|
||||
TF->EvalDeadSymbols(Tmp, *this, *Builder, EntryNode->getLocation(),
|
||||
EntryNode, CleanedState, DeadSymbols);
|
||||
TF->EvalDeadSymbols(Tmp, *this, *Builder, EntryNode, S,
|
||||
CleanedState, DeadSymbols);
|
||||
|
||||
if (!Builder->BuildSinks && !Builder->HasGeneratedNode)
|
||||
Tmp.Add(EntryNode);
|
||||
|
|
|
@ -129,14 +129,22 @@ ValueStateManager::RemoveDeadBindings(ValueState* St, Stmt* Loc,
|
|||
}
|
||||
|
||||
// Remove dead variable bindings.
|
||||
for (ValueState::vb_iterator I = St->vb_begin(), E = St->vb_end(); I!=E ; ++I)
|
||||
if (!Marked.count(I.getKey()))
|
||||
NewSt.VarBindings = Remove(NewSt, I.getKey());
|
||||
|
||||
// Remove dead symbols.
|
||||
|
||||
DeadSymbols.clear();
|
||||
|
||||
for (ValueState::vb_iterator I = St->vb_begin(), E = St->vb_end(); I!=E ; ++I)
|
||||
if (!Marked.count(I.getKey())) {
|
||||
NewSt.VarBindings = Remove(NewSt, I.getKey());
|
||||
|
||||
RVal X = I.getData();
|
||||
|
||||
for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
|
||||
SI != SE; ++SI)
|
||||
if (!MarkedSymbols.count(*SI)) DeadSymbols.insert(*SI);
|
||||
}
|
||||
|
||||
// Remove dead symbols.
|
||||
|
||||
for (ValueState::ce_iterator I = St->ce_begin(), E=St->ce_end(); I!=E; ++I) {
|
||||
|
||||
SymbolID sym = I.getKey();
|
||||
|
|
|
@ -84,3 +84,11 @@ CFDateRef f6(int x) {
|
|||
return date; // expected-warning{{leak}}
|
||||
}
|
||||
|
||||
// Test a leak involving an overwrite.
|
||||
|
||||
CFDateRef f7() {
|
||||
CFDateRef date = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
|
||||
CFRetain(date);
|
||||
date = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()); //expected-warning{{leak}}
|
||||
return date;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче