Removed static analysis-specific diagnostics from DiagnosticKinds.def.

Use custom diagnostics for static analysis checkers.  Added warnings
for dereferencing uninitialized values and divide-by-zeroes.

llvm-svn: 47626
This commit is contained in:
Ted Kremenek 2008-02-26 21:31:18 +00:00
parent c24ea4fb41
commit e9f30d3288
4 changed files with 61 additions and 24 deletions

View File

@ -1545,7 +1545,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
GraphPrintCheckerState->isExplicitNullDeref(N) ||
GraphPrintCheckerState->isUninitDeref(N) ||
GraphPrintCheckerState->isUninitStore(N) ||
GraphPrintCheckerState->isUninitControlFlow(N))
GraphPrintCheckerState->isUninitControlFlow(N) ||
GraphPrintCheckerState->isBadDivide(N))
return "color=\"red\",style=\"filled\"";
return "";
@ -1586,6 +1587,9 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
else if (GraphPrintCheckerState->isUninitStore(N)) {
Out << "\\|Store to Uninitialized LVal.";
}
else if (GraphPrintCheckerState->isBadDivide(N)) {
Out << "\\|Divide-by zero or uninitialized value.";
}
break;
}

View File

@ -19,6 +19,27 @@
using namespace clang;
namespace clang {
template <typename ITERATOR>
static void EmitWarning(Diagnostic& Diag, SourceManager& SrcMgr,
ITERATOR I, ITERATOR E, const char* msg) {
bool isFirst;
unsigned ErrorDiag;
for (; I != E; ++I) {
if (isFirst) {
isFirst = false;
ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, msg);
}
const PostStmt& L = cast<PostStmt>((*I)->getLocation());
Expr* Exp = cast<Expr>(L.getStmt());
Diag.Report(FullSourceLoc(Exp->getExprLoc(), SrcMgr), ErrorDiag);
}
}
unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
Diagnostic& Diag, bool Visualize) {
@ -32,18 +53,29 @@ unsigned RunGRSimpleVals(CFG& cfg, FunctionDecl& FD, ASTContext& Ctx,
CheckerState->setTransferFunctions(GRSV);
// Execute the worklist algorithm.
Engine.ExecuteWorkList(10000);
Engine.ExecuteWorkList(20000);
// Look for explicit-Null dereferences and warn about them.
for (GRExprEngine::null_iterator I=CheckerState->null_begin(),
E=CheckerState->null_end(); I!=E; ++I) {
const PostStmt& L = cast<PostStmt>((*I)->getLocation());
Expr* Exp = cast<Expr>(L.getStmt());
Diag.Report(FullSourceLoc(Exp->getExprLoc(), Ctx.getSourceManager()),
diag::chkr_null_deref_after_check);
}
SourceManager& SrcMgr = Ctx.getSourceManager();
EmitWarning(Diag, SrcMgr,
CheckerState->null_derefs_begin(),
CheckerState->null_derefs_end(),
"NULL pointer is dereferenced after it is checked for NULL.");
EmitWarning(Diag, SrcMgr,
CheckerState->uninit_derefs_begin(),
CheckerState->uninit_derefs_end(),
"Dereference of uninitialized value.");
EmitWarning(Diag, SrcMgr,
CheckerState->uninit_derefs_begin(),
CheckerState->uninit_derefs_end(),
"Dereference of uninitialized value.");
EmitWarning(Diag, SrcMgr,
CheckerState->bad_divides_begin(),
CheckerState->bad_divides_end(),
"Division by zero/uninitialized value.");
#ifndef NDEBUG
if (Visualize) CheckerState->ViewGraph();

View File

@ -117,7 +117,7 @@ protected:
typedef llvm::SmallPtrSet<NodeTy*,5> UninitStoresTy;
typedef llvm::SmallPtrSet<NodeTy*,5> BadDerefTy;
typedef llvm::SmallPtrSet<NodeTy*,5> DivZerosTy;
typedef llvm::SmallPtrSet<NodeTy*,5> BadDividesTy;
/// UninitStores - Sinks in the ExplodedGraph that result from
/// making a store to an uninitialized lvalue.
@ -137,7 +137,7 @@ protected:
/// BadDivides - Nodes in the ExplodedGraph that result from evaluating
/// a divide-by-zero or divide-by-uninitialized.
DivZerosTy BadDivides;
BadDividesTy BadDivides;
bool StateCleaned;
@ -198,9 +198,17 @@ public:
return N->isSink() && BadDivides.count(const_cast<NodeTy*>(N)) != 0;
}
typedef BadDerefTy::iterator null_iterator;
null_iterator null_begin() { return ExplicitNullDeref.begin(); }
null_iterator null_end() { return ExplicitNullDeref.end(); }
typedef BadDerefTy::iterator null_deref_iterator;
null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); }
null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }
typedef BadDerefTy::iterator uninit_deref_iterator;
uninit_deref_iterator uninit_derefs_begin() { return UninitDeref.begin(); }
uninit_deref_iterator uninit_derefs_end() { return UninitDeref.end(); }
typedef BadDividesTy::iterator bad_divide_iterator;
bad_divide_iterator bad_divides_begin() { return BadDivides.begin(); }
bad_divide_iterator bad_divides_end() { return BadDivides.end(); }
/// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.

View File

@ -966,11 +966,4 @@ DIAG(ext_return_missing_expr, EXTENSION,
DIAG(ext_return_has_expr, EXTENSION,
"void function '%0' should not return a value")
//===----------------------------------------------------------------------===//
// Static Analysis Warnings (Bug-Finding)
//===----------------------------------------------------------------------===//
DIAG(chkr_null_deref_after_check, ERROR,
"NULL pointer is dereferenced after it is checked for NULL.")
#undef DIAG