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:
parent
c24ea4fb41
commit
e9f30d3288
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue