From 2d46f4dc297b32eff154a26c0e3bc16b6c66b78c Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Sat, 20 Mar 2010 01:17:30 +0000 Subject: [PATCH] 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 --- .../clang/Checker/BugReporter/BugReporter.h | 2 + lib/Checker/BugReporter.cpp | 2 + lib/Checker/BugReporterVisitors.cpp | 51 +++++++++++++++++-- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/include/clang/Checker/BugReporter/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h index 6c41668cce..da91e126f0 100644 --- a/include/clang/Checker/BugReporter/BugReporter.h +++ b/include/clang/Checker/BugReporter/BugReporter.h @@ -467,6 +467,8 @@ void registerTrackNullOrUndefValue(BugReporterContext& BRC, const void *stmt, void registerFindLastStore(BugReporterContext& BRC, const void *memregion, const ExplodedNode *N); +void registerNilReceiverVisitor(BugReporterContext &BRC); + } // end namespace clang::bugreporter diff --git a/lib/Checker/BugReporter.cpp b/lib/Checker/BugReporter.cpp index 0cf593b260..c7438447bb 100644 --- a/lib/Checker/BugReporter.cpp +++ b/lib/Checker/BugReporter.cpp @@ -1613,7 +1613,9 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, else return; + // Register node visitors. R->registerInitialVisitors(PDB, N); + bugreporter::registerNilReceiverVisitor(PDB); switch (PDB.getGenerationScheme()) { case PathDiagnosticClient::Extensive: 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(R)) { if (const PostStmt *P = Node->getLocationAs()) if (const DeclStmt *DS = P->getStmtAs()) @@ -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(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(); + if (!P) + return 0; + const ObjCMessageExpr *ME = P->getStmtAs(); + 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(&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()); +} -- 2.50.1