[cfe-commits] r49119 - /cfe/trunk/lib/Analysis/GRSimpleVals.cpp
Ted Kremenek
kremenek at apple.com
Wed Apr 2 15:03:55 PDT 2008
Author: kremenek
Date: Wed Apr 2 17:03:53 2008
New Revision: 49119
URL: http://llvm.org/viewvc/llvm-project?rev=49119&view=rev
Log:
Added more PathDiagnostic rendering for terminators: switch, goto, loops.
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=49119&r1=49118&r2=49119&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRSimpleVals.cpp (original)
+++ cfe/trunk/lib/Analysis/GRSimpleVals.cpp Wed Apr 2 17:03:53 2008
@@ -15,6 +15,7 @@
#include "GRSimpleVals.h"
#include "BasicObjCFoundationChecks.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Analysis/PathSensitive/ValueState.h"
#include "clang/Analysis/PathDiagnostic.h"
#include <sstream>
@@ -83,6 +84,9 @@
else if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
return BE->getSrc()->getTerminator();
}
+ else if (const BlockEntrance* BE = dyn_cast<BlockEntrance>(&P)) {
+ return BE->getFirstStmt();
+ }
assert (false && "Unsupported ProgramPoint.");
return NULL;
@@ -163,44 +167,140 @@
//===----------------------------------------------------------------------===//
static void GeneratePathDiagnostic(PathDiagnostic& PD,
- SourceManager& SMgr,
+ ASTContext& Ctx,
ExplodedNode<ValueState>* N) {
- if (N->pred_empty())
- return;
-
- N = *(N->pred_begin());
+ SourceManager& SMgr = Ctx.getSourceManager();
- ProgramPoint P = N->getLocation();
+ while (!N->pred_empty()) {
- if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
-
- CFGBlock* Src = BE->getSrc();
- CFGBlock* Dst = BE->getDst();
+ ExplodedNode<ValueState>* LastNode = N;
+ N = *(N->pred_begin());
- // FIXME: Better handling for switches.
+ ProgramPoint P = N->getLocation();
- if (Src->succ_size() == 2) {
+ if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
- Stmt* T = Src->getTerminator();
+ CFGBlock* Src = BE->getSrc();
+ CFGBlock* Dst = BE->getDst();
- if (!Src)
- return;
+ Stmt* T = Src->getTerminator();
+ if (!T)
+ continue;
+
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);
+ switch (T->getStmtClass()) {
+ default:
+ break;
+
+ case Stmt::GotoStmtClass:
+ case Stmt::IndirectGotoStmtClass: {
+
+ Stmt* S = GetStmt(LastNode->getLocation());
+
+ if (!S)
+ continue;
+
+ std::ostringstream os;
+
+ os << "Control jumps to line "
+ << SMgr.getLogicalLineNumber(S->getLocStart()) << ".\n";
+
+ PD.push_front(new PathDiagnosticPiece(L, os.str()));
+ break;
+ }
+
+ case Stmt::SwitchStmtClass: {
+
+ // Figure out what case arm we took.
+
+ Stmt* S = Dst->getLabel();
+
+ if (!S)
+ continue;
+
+ std::ostringstream os;
+
+ switch (S->getStmtClass()) {
+ default:
+ continue;
+
+ case Stmt::DefaultStmtClass: {
+
+ os << "Control jumps to the 'default' case at line "
+ << SMgr.getLogicalLineNumber(S->getLocStart()) << ".\n";
+
+ break;
+ }
+
+ case Stmt::CaseStmtClass: {
+
+ os << "Control jumps to 'case ";
+
+ Expr* CondE = cast<SwitchStmt>(T)->getCond();
+ unsigned bits = Ctx.getTypeSize(CondE->getType());
+
+ llvm::APSInt V1(bits, false);
+
+ CaseStmt* Case = cast<CaseStmt>(S);
+
+ if (!Case->getLHS()->isIntegerConstantExpr(V1, Ctx, 0, true)) {
+ assert (false &&
+ "Case condition must evaluate to an integer constant.");
+ continue;
+ }
+
+ os << V1.toString();
+
+ // Get the RHS of the case, if it exists.
+
+ if (Expr* E = Case->getRHS()) {
+
+ llvm::APSInt V2(bits, false);
+
+ if (!E->isIntegerConstantExpr(V2, Ctx, 0, true)) {
+ assert (false &&
+ "Case condition (RHS) must evaluate to an integer constant.");
+ continue;
+ }
+
+ os << " .. " << V2.toString();
+ }
+
+ os << ":' at line "
+ << SMgr.getLogicalLineNumber(S->getLocStart()) << ".\n";
+
+ break;
+
+ }
+ }
+
+ PD.push_front(new PathDiagnosticPiece(L, os.str()));
+ break;
+ }
+
+
+ case Stmt::DoStmtClass:
+ case Stmt::WhileStmtClass:
+ case Stmt::ForStmtClass:
+ case Stmt::IfStmtClass: {
+
+ 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."));
+
+ break;
+ }
+ }
+ }
+ }
}
template <typename ITERATOR, typename DESC>
-static void Report(PathDiagnosticClient& PDC, SourceManager& SMgr, DESC,
+static void Report(PathDiagnosticClient& PDC, ASTContext& Ctx, DESC,
ITERATOR I, ITERATOR E) {
@@ -228,10 +328,10 @@
PathDiagnostic D(BugName);
// Get the end-of-path diagnostic.
- D.push_back(DESC::getEndPath(SMgr, GetNode(I)));
+ D.push_back(DESC::getEndPath(Ctx.getSourceManager(), GetNode(I)));
// Generate the rest of the diagnostic.
- GeneratePathDiagnostic(D, SMgr, GetNode(I));
+ GeneratePathDiagnostic(D, Ctx, GetNode(I));
PDC.HandlePathDiagnostic(D);
}
@@ -271,7 +371,7 @@
CS->null_derefs_begin(), CS->null_derefs_end(),
"Dereference of NULL pointer.");
else
- Report(*PD, SrcMgr, bugdesc::NullDeref(),
+ Report(*PD, Ctx, bugdesc::NullDeref(),
CS->null_derefs_begin(), CS->null_derefs_end());
More information about the cfe-commits
mailing list