aboutsummaryrefslogtreecommitdiff
path: root/lib/Checker/BugReporterVisitors.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-03-20 01:17:30 +0000
committerTed Kremenek <kremenek@apple.com>2010-03-20 01:17:30 +0000
commit2d46f4dc297b32eff154a26c0e3bc16b6c66b78c (patch)
tree8b440336cff60f42840c4e9d54e06728f19f3cdd /lib/Checker/BugReporterVisitors.cpp
parent365b0bd38964c57f7e9fcace1eaf9877fb3b0485 (diff)
Augment path diagnostics to include displaying when a message expression
is not evaluated because the receiver is nil. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99024 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Checker/BugReporterVisitors.cpp')
-rw-r--r--lib/Checker/BugReporterVisitors.cpp51
1 files changed, 47 insertions, 4 deletions
diff --git a/lib/Checker/BugReporterVisitors.cpp b/lib/Checker/BugReporterVisitors.cpp
index 6cf41b14dc..6cf6d92efb 100644
--- a/lib/Checker/BugReporterVisitors.cpp
+++ b/lib/Checker/BugReporterVisitors.cpp
@@ -103,7 +103,6 @@ public:
const ExplodedNode *Node = N, *Last = NULL;
for ( ; Node ; Last = Node, Node = Node->getFirstPred()) {
-
if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
if (const PostStmt *P = Node->getLocationAs<PostStmt>())
if (const DeclStmt *DS = P->getStmtAs<DeclStmt>())
@@ -248,7 +247,6 @@ public:
// Check if in the previous state it was feasible for this constraint
// to *not* be true.
if (PrevN->getState()->Assume(Constraint, !Assumption)) {
-
isSatisfied = true;
// As a sanity check, make sure that the negation of the constraint
@@ -259,8 +257,8 @@ public:
// We found the transition point for the constraint. We now need to
// pretty-print the constraint. (work-in-progress)
- std::string sbuf;
- llvm::raw_string_ostream os(sbuf);
+ llvm::SmallString<256> sbuf;
+ llvm::raw_svector_ostream os(sbuf);
if (isa<Loc>(Constraint)) {
os << "Assuming pointer value is ";
@@ -365,3 +363,48 @@ void clang::bugreporter::registerFindLastStore(BugReporterContext& BRC,
BRC.addVisitor(new FindLastStoreBRVisitor(V, R));
}
+
+namespace {
+class NilReceiverVisitor : public BugReporterVisitor {
+public:
+ NilReceiverVisitor() {}
+
+ PathDiagnosticPiece* VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext& BRC) {
+
+ const PostStmt *P = N->getLocationAs<PostStmt>();
+ if (!P)
+ return 0;
+ const ObjCMessageExpr *ME = P->getStmtAs<ObjCMessageExpr>();
+ if (!ME)
+ return 0;
+ const Expr *Receiver = ME->getReceiver();
+ if (!Receiver)
+ return 0;
+ const GRState *state = N->getState();
+ const SVal &V = state->getSVal(Receiver);
+ const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
+ if (!DV)
+ return 0;
+
+ state = state->Assume(*DV, true);
+ if (state)
+ return 0;
+
+ // The receiver was nil, and hence the method was skipped.
+ // Register a BugReporterVisitor to issue a message telling us how
+ // the receiver was null.
+ bugreporter::registerTrackNullOrUndefValue(BRC, Receiver, N);
+
+ //Issue a message saying that the method was skipped.
+ PathDiagnosticLocation L(Receiver, BRC.getSourceManager());
+ return new PathDiagnosticEventPiece(L, "No method actually called "
+ "because the receiver is nil");
+ }
+};
+} // end anonymous namespace
+
+void clang::bugreporter::registerNilReceiverVisitor(BugReporterContext &BRC) {
+ BRC.addVisitor(new NilReceiverVisitor());
+}