[cfe-commits] r49086 - /cfe/trunk/lib/Analysis/GRSimpleVals.cpp
Ted Kremenek
kremenek at apple.com
Wed Apr 2 00:05:46 PDT 2008
Author: kremenek
Date: Wed Apr 2 02:05:46 2008
New Revision: 49086
URL: http://llvm.org/viewvc/llvm-project?rev=49086&view=rev
Log:
Beginning of some cleanups; start generating path diagnostics using objects
that describe a bug.
Modified:
cfe/trunk/lib/Analysis/GRSimpleVals.cpp
Modified: cfe/trunk/lib/Analysis/GRSimpleVals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRSimpleVals.cpp?rev=49086&r1=49085&r2=49086&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRSimpleVals.cpp (original)
+++ cfe/trunk/lib/Analysis/GRSimpleVals.cpp Wed Apr 2 02:05:46 2008
@@ -21,8 +21,40 @@
using namespace clang;
-namespace clang {
+//===----------------------------------------------------------------------===//
+// Bug Descriptions.
+//===----------------------------------------------------------------------===//
+
+namespace bugdesc {
+struct NullDeref {
+ static const char* getName() { return "Null pointer dereference"; }
+
+ static PathDiagnosticPiece* getEndPath(SourceManager& SMgr,
+ ExplodedNode<ValueState> *N);
+};
+
+PathDiagnosticPiece* NullDeref::getEndPath(SourceManager& SMgr,
+ ExplodedNode<ValueState> *N) {
+
+ Expr* E = cast<Expr>(cast<PostStmt>(N->getLocation()).getStmt());
+
+ // FIXME: Do better ranges for different kinds of null dereferences.
+
+ FullSourceLoc L(E->getLocStart(), SMgr);
+
+ PathDiagnosticPiece* P = new PathDiagnosticPiece(L, getName());
+ P->addRange(E->getSourceRange());
+
+ return P;
+}
+
+} // end namespace: bugdesc
+
+//===----------------------------------------------------------------------===//
+// Utility functions.
+//===----------------------------------------------------------------------===//
+
template <typename ITERATOR>
static inline ExplodedNode<ValueState>* GetNode(ITERATOR I) {
return *I;
@@ -55,88 +87,6 @@
assert (false && "Unsupported ProgramPoint.");
return NULL;
}
-
-
-//===----------------------------------------------------------------------===//
-// Path Warnings.
-//===----------------------------------------------------------------------===//
-
-static inline SourceLocation GetSourceLoc(ProgramPoint P) {
-
- if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
- return PS->getStmt()->getLocStart();
- }
- else if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
- return BE->getSrc()->getTerminator()->getLocStart();
- }
-
- return SourceLocation();
-}
-
-static inline
-FullSourceLoc GetFullSourceLoc(SourceManager& SMgr, ProgramPoint P) {
- return FullSourceLoc(GetSourceLoc(P), SMgr);
-}
-
-template <typename ITERATOR>
-static void EmitPathWarning(Diagnostic& Diag, PathDiagnosticClient* PD,
- SourceManager& SrcMgr, const std::string& msg,
- ITERATOR I) {
-
-
- PathDiagnostic D;
-
- { // Add the end message.
-
- ProgramPoint P = GetLocation(I);
- D.push_back(new PathDiagnosticPiece(GetFullSourceLoc(SrcMgr, P), msg));
- }
-
- // Walk up the path.
-
- ExplodedNode<ValueState> *N = GetNode(I);
-
- while (N) {
-
- if (N->pred_empty())
- break;
-
- N = *(N->pred_begin()); // Grab the first predecessor.
-
- ProgramPoint P = N->getLocation();
-
- if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
-
- CFGBlock* Src = BE->getSrc();
- CFGBlock* Dst = BE->getDst();
-
- // FIXME: Better handling for switches.
-
- if (Src->succ_size() == 2) {
-
- Stmt* T = Src->getTerminator();
-
- if (!Src)
- continue;
-
- if (*(Src->succ_begin()+1) == Dst) {
- D.push_front(new PathDiagnosticPiece(FullSourceLoc(T->getLocStart(),
- SrcMgr),
- "Taking false branch."));
-
- }
- else {
- D.push_front(new PathDiagnosticPiece(FullSourceLoc(T->getLocStart(),
- SrcMgr),
- "Taking true branch."));
- }
- }
- }
- }
-
- // Emit the path.
- PD->HandlePathDiagnostic(D);
-}
//===----------------------------------------------------------------------===//
// Pathless Warnings
@@ -168,9 +118,9 @@
}
template <typename ITERATOR>
-void EmitWarning(Diagnostic& Diag, PathDiagnosticClient* PD,
- SourceManager& SrcMgr,
- ITERATOR I, ITERATOR E, const char* msg) {
+static void EmitWarning(Diagnostic& Diag, PathDiagnosticClient* PD,
+ SourceManager& SrcMgr,
+ ITERATOR I, ITERATOR E, const char* msg) {
std::ostringstream Out;
std::string Str(msg);
@@ -204,92 +154,175 @@
CachedErrors.insert(p);
}
- if (PD)
- EmitPathWarning(Diag, PD, SrcMgr, Str, I);
- else
- EmitDiag(Diag, PD, SrcMgr, ErrorDiag, I);
+ EmitDiag(Diag, PD, SrcMgr, ErrorDiag, I);
}
}
//===----------------------------------------------------------------------===//
+// Path warnings.
+//===----------------------------------------------------------------------===//
+
+static void GeneratePathDiagnostic(PathDiagnostic& PD,
+ SourceManager& SMgr,
+ ExplodedNode<ValueState>* N) {
+
+ if (N->pred_empty())
+ return;
+
+ N = *(N->pred_begin());
+
+ ProgramPoint P = N->getLocation();
+
+ if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
+
+ CFGBlock* Src = BE->getSrc();
+ CFGBlock* Dst = BE->getDst();
+
+ // FIXME: Better handling for switches.
+
+ if (Src->succ_size() == 2) {
+
+ Stmt* T = Src->getTerminator();
+
+ if (!Src)
+ return;
+
+ FullSourceLoc L(T->getLocStart(), SMgr);
+
+ if (*(Src->succ_begin()+1) == Dst)
+ PD.push_front(new PathDiagnosticPiece(L, "Taking false branch."));
+ else
+ PD.push_front(new PathDiagnosticPiece(L, "Taking true branch."));
+ }
+ }
+
+ GeneratePathDiagnostic(PD, SMgr, N);
+}
+
+template <typename ITERATOR, typename DESC>
+static void Report(PathDiagnosticClient& PDC, SourceManager& SMgr, DESC,
+ ITERATOR I, ITERATOR E) {
+
+
+ if (I == E)
+ return;
+
+ const char* BugName = DESC::getName();
+
+ llvm::SmallPtrSet<void*,10> CachedErrors;
+
+ for (; I != E; ++I) {
+
+ // HACK: Cache the location of the error. Don't emit the same
+ // warning for the same error type that occurs at the same program
+ // location but along a different path.
+ void* p = GetLocation(I).getRawData();
+
+ if (CachedErrors.count(p))
+ continue;
+
+ CachedErrors.insert(p);
+
+ // Create the PathDiagnostic.
+
+ PathDiagnostic D(BugName);
+
+ // Get the end-of-path diagnostic.
+ D.push_back(DESC::getEndPath(SMgr, GetNode(I)));
+
+ // Generate the rest of the diagnostic.
+ GeneratePathDiagnostic(D, SMgr, GetNode(I));
+
+ PDC.HandlePathDiagnostic(D);
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
// Analysis Driver.
//===----------------------------------------------------------------------===//
+namespace clang {
+
unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx,
- Diagnostic& Diag, PathDiagnosticClient* PD,
- bool Visualize, bool TrimGraph) {
+ Diagnostic& Diag, PathDiagnosticClient* PD,
+ bool Visualize, bool TrimGraph) {
GRCoreEngine<GRExprEngine> Eng(cfg, CD, Ctx);
- GRExprEngine* CheckerState = &Eng.getCheckerState();
+ GRExprEngine* CS = &Eng.getCheckerState();
// Set base transfer functions.
GRSimpleVals GRSV;
- CheckerState->setTransferFunctions(GRSV);
+ CS->setTransferFunctions(GRSV);
// Add extra checkers.
llvm::OwningPtr<GRSimpleAPICheck> FoundationCheck(
- CreateBasicObjCFoundationChecks(Ctx, &CheckerState->getStateManager()));
+ CreateBasicObjCFoundationChecks(Ctx, &CS->getStateManager()));
- CheckerState->AddObjCMessageExprCheck(FoundationCheck.get());
+ CS->AddObjCMessageExprCheck(FoundationCheck.get());
// Execute the worklist algorithm.
Eng.ExecuteWorkList(120000);
SourceManager& SrcMgr = Ctx.getSourceManager();
- EmitWarning(Diag, PD, SrcMgr,
- CheckerState->null_derefs_begin(),
- CheckerState->null_derefs_end(),
- "Dereference of NULL pointer.");
+ if (!PD)
+ EmitWarning(Diag, PD, SrcMgr,
+ CS->null_derefs_begin(), CS->null_derefs_end(),
+ "Dereference of NULL pointer.");
+ else
+ Report(*PD, SrcMgr, bugdesc::NullDeref(),
+ CS->null_derefs_begin(), CS->null_derefs_end());
+
EmitWarning(Diag, PD, SrcMgr,
- CheckerState->undef_derefs_begin(),
- CheckerState->undef_derefs_end(),
+ CS->undef_derefs_begin(),
+ CS->undef_derefs_end(),
"Dereference of undefined value.");
EmitWarning(Diag, PD, SrcMgr,
- CheckerState->undef_branches_begin(),
- CheckerState->undef_branches_end(),
+ CS->undef_branches_begin(),
+ CS->undef_branches_end(),
"Branch condition evaluates to an uninitialized value.");
EmitWarning(Diag, PD, SrcMgr,
- CheckerState->explicit_bad_divides_begin(),
- CheckerState->explicit_bad_divides_end(),
+ CS->explicit_bad_divides_begin(),
+ CS->explicit_bad_divides_end(),
"Division by zero/undefined value.");
EmitWarning(Diag, PD, SrcMgr,
- CheckerState->undef_results_begin(),
- CheckerState->undef_results_end(),
+ CS->undef_results_begin(),
+ CS->undef_results_end(),
"Result of operation is undefined.");
EmitWarning(Diag, PD, SrcMgr,
- CheckerState->bad_calls_begin(),
- CheckerState->bad_calls_end(),
+ CS->bad_calls_begin(),
+ CS->bad_calls_end(),
"Call using a NULL or undefined function pointer value.");
EmitWarning(Diag, PD, SrcMgr,
- CheckerState->undef_arg_begin(),
- CheckerState->undef_arg_end(),
+ CS->undef_arg_begin(),
+ CS->undef_arg_end(),
"Pass-by-value argument in function is undefined.");
EmitWarning(Diag, PD, SrcMgr,
- CheckerState->msg_expr_undef_arg_begin(),
- CheckerState->msg_expr_undef_arg_end(),
+ CS->msg_expr_undef_arg_begin(),
+ CS->msg_expr_undef_arg_end(),
"Pass-by-value argument in message expression is undefined.");
EmitWarning(Diag, PD, SrcMgr,
- CheckerState->undef_receivers_begin(),
- CheckerState->undef_receivers_end(),
+ CS->undef_receivers_begin(),
+ CS->undef_receivers_end(),
"Receiver in message expression is an uninitialized value.");
EmitWarning(Diag, PD, SrcMgr,
- CheckerState->ret_stackaddr_begin(),
- CheckerState->ret_stackaddr_end(),
+ CS->ret_stackaddr_begin(),
+ CS->ret_stackaddr_end(),
"Address of stack-allocated variable returned.");
FoundationCheck.get()->ReportResults(Diag);
#ifndef NDEBUG
- if (Visualize) CheckerState->ViewGraph(TrimGraph);
+ if (Visualize) CS->ViewGraph(TrimGraph);
#endif
return Eng.getGraph().size();
More information about the cfe-commits
mailing list