[cfe-commits] r51453 - in /cfe/trunk/lib/Analysis: BugReporter.cpp CFRefCount.cpp
Ted Kremenek
kremenek at apple.com
Thu May 22 16:45:20 PDT 2008
Author: kremenek
Date: Thu May 22 18:45:19 2008
New Revision: 51453
URL: http://llvm.org/viewvc/llvm-project?rev=51453&view=rev
Log:
Prototyped support in the BugReporter to emit diagnostics of the form "p now aliases q".
Modified:
cfe/trunk/lib/Analysis/BugReporter.cpp
cfe/trunk/lib/Analysis/CFRefCount.cpp
Modified: cfe/trunk/lib/Analysis/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BugReporter.cpp?rev=51453&r1=51452&r2=51453&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BugReporter.cpp (original)
+++ cfe/trunk/lib/Analysis/BugReporter.cpp Thu May 22 18:45:19 2008
@@ -30,7 +30,13 @@
BugReport::~BugReport() {}
RangedBugReport::~RangedBugReport() {}
-ExplodedGraph<ValueState>& BugReporter::getGraph() { return Eng.getGraph(); }
+ExplodedGraph<ValueState>& BugReporter::getGraph() {
+ return Eng.getGraph();
+}
+
+ValueStateManager& BugReporter::getStateManager() {
+ return Eng.getStateManager();
+}
static inline Stmt* GetStmt(const ProgramPoint& P) {
if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
@@ -214,6 +220,126 @@
return std::make_pair(G, First);
}
+static VarDecl* GetMostRecentVarDeclBinding(ExplodedNode<ValueState>* N,
+ ValueStateManager& VMgr,
+ RVal X) {
+
+ for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) {
+
+ ProgramPoint P = N->getLocation();
+
+ if (!isa<PostStmt>(P))
+ continue;
+
+ DeclRefExpr* DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt());
+
+ if (!DR)
+ continue;
+
+ RVal Y = VMgr.GetRVal(N->getState(), DR);
+
+ if (X != Y)
+ continue;
+
+ VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl());
+
+ if (!VD)
+ continue;
+
+ return VD;
+ }
+
+ return 0;
+}
+
+
+static void HandleNotableSymbol(ExplodedNode<ValueState>* N, Stmt* S,
+ SymbolID Sym, BugReporter& BR,
+ PathDiagnostic& PD) {
+
+ ExplodedNode<ValueState>* Pred = N->pred_empty() ? 0 : *N->pred_begin();
+ ValueState* PrevSt = Pred ? Pred->getState() : 0;
+
+ if (!PrevSt)
+ return;
+
+ // Look at the variable bindings of the current state that map to the
+ // specified symbol. Are any of them not in the previous state.
+
+ ValueState* St = N->getState();
+ ValueStateManager& VMgr = BR.getStateManager();
+
+ // FIXME: Later generalize for a broader memory model.
+
+ // FIXME: This is quadratic, since its nested in another loop. Probably
+ // doesn't matter, but keep an eye out for performance issues. It's
+ // also a bunch of copy-paste. Bad. Cleanup later.
+
+ for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I){
+
+ RVal V = I.getData();
+ SymbolID ScanSym;
+
+ if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&V))
+ ScanSym = SV->getSymbol();
+ else if (nonlval::SymbolVal* SV = dyn_cast<nonlval::SymbolVal>(&V))
+ ScanSym = SV->getSymbol();
+ else
+ continue;
+
+ if (ScanSym != Sym)
+ continue;
+
+ // Check if the previous state has this binding.
+
+ RVal X = VMgr.GetRVal(PrevSt, lval::DeclVal(I.getKey()));
+
+ if (X == V) // Same binding?
+ continue;
+
+ // Different binding. Only handle assignments for now. We don't pull
+ // this check out of the loop because we will eventually handle other
+ // cases.
+
+ VarDecl *VD = 0;
+
+ if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
+ if (!B->isAssignmentOp())
+ continue;
+
+ // What variable did we assign to?
+ DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts());
+
+ if (!DR)
+ continue;
+
+ VD = dyn_cast<VarDecl>(DR->getDecl());
+ }
+ else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
+ VD = dyn_cast<VarDecl>(DS->getDecl());
+
+ if (!VD)
+ continue;
+
+ // What is the most recently referenced variable with this binding?
+ VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
+
+ if (!MostRecent)
+ continue;
+
+ // Create the diagnostic.
+
+ FullSourceLoc L(S->getLocStart(), BR.getSourceManager());
+
+ if (VD->getType()->isPointerLikeType()) {
+ std::string msg = "'" + std::string(VD->getName()) +
+ "' now aliases '" + MostRecent->getName() + "'";
+
+ PD.push_front(new PathDiagnosticPiece(L, msg));
+ }
+ }
+}
+
void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
BugReport& R) {
@@ -433,10 +559,49 @@
}
if (PathDiagnosticPiece* p = R.VisitNode(N, NextNode, *ReportGraph, *this))
- PD.push_front(p);
+ PD.push_front(p);
+
+ if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
+
+ ValueState* St = N->getState();
+
+ // Scan the lval bindings, and see if a "notable" symbol has a new
+ // lval binding.
+
+ // FIXME: In the future, when we generalize the memory model, we'll
+ // need a way to iterate over binded locations.
+
+ llvm::SmallSet<SymbolID, 10> AlreadyProcessed;
+
+ for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I){
+
+ RVal V = I.getData();
+ SymbolID ScanSym;
+
+ if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&V))
+ ScanSym = SV->getSymbol();
+ else if (nonlval::SymbolVal* SV = dyn_cast<nonlval::SymbolVal>(&V))
+ ScanSym = SV->getSymbol();
+ else
+ continue;
+
+ assert (ScanSym.isInitialized());
+
+ if (!isNotable(ScanSym))
+ continue;
+
+ if (AlreadyProcessed.count(ScanSym))
+ continue;
+
+ AlreadyProcessed.insert(ScanSym);
+
+ HandleNotableSymbol(N, PS->getStmt(), ScanSym, *this, PD);
+ }
+ }
}
}
+
bool BugTypeCacheLocation::isCached(BugReport& R) {
ExplodedNode<ValueState>* N = R.getEndNode();
Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=51453&r1=51452&r2=51453&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Thu May 22 18:45:19 2008
@@ -2017,6 +2017,10 @@
PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR,
ExplodedNode<ValueState>* EndN) {
+
+ // Tell the BugReporter to report cases when the tracked symbol is
+ // assigned to different variables, etc.
+ BR.addNotableSymbol(Sym);
if (!getBugType().isLeak())
return RangedBugReport::getEndPath(BR, EndN);
More information about the cfe-commits
mailing list