From e9f30d32886df0995786283f1d4c1fa48724b127 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Tue, 26 Feb 2008 21:31:18 +0000 Subject: [PATCH] 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 --- clang/Analysis/GRExprEngine.cpp | 6 ++- clang/Analysis/GRSimpleVals.cpp | 54 +++++++++++++++---- .../Analysis/PathSensitive/GRExprEngine.h | 18 +++++-- clang/include/clang/Basic/DiagnosticKinds.def | 7 --- 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/clang/Analysis/GRExprEngine.cpp b/clang/Analysis/GRExprEngine.cpp index 1dae433e8fd7..0630fc5fb090 100644 --- a/clang/Analysis/GRExprEngine.cpp +++ b/clang/Analysis/GRExprEngine.cpp @@ -1545,7 +1545,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits : 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 : else if (GraphPrintCheckerState->isUninitStore(N)) { Out << "\\|Store to Uninitialized LVal."; } + else if (GraphPrintCheckerState->isBadDivide(N)) { + Out << "\\|Divide-by zero or uninitialized value."; + } break; } diff --git a/clang/Analysis/GRSimpleVals.cpp b/clang/Analysis/GRSimpleVals.cpp index 04a13e370351..549aa0bb4ff3 100644 --- a/clang/Analysis/GRSimpleVals.cpp +++ b/clang/Analysis/GRSimpleVals.cpp @@ -19,6 +19,27 @@ using namespace clang; namespace clang { + +template +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((*I)->getLocation()); + Expr* Exp = cast(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((*I)->getLocation()); - Expr* Exp = cast(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(); diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h index 08d249519668..a5f88354b8f8 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -117,7 +117,7 @@ protected: typedef llvm::SmallPtrSet UninitStoresTy; typedef llvm::SmallPtrSet BadDerefTy; - typedef llvm::SmallPtrSet DivZerosTy; + typedef llvm::SmallPtrSet 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(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. diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 902ecc217e0c..21f348216daf 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -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