]> granicus.if.org Git - clang/commitdiff
Reapply r99024 (but with the memory issue now fixed).
authorTed Kremenek <kremenek@apple.com>
Sat, 20 Mar 2010 18:02:01 +0000 (18:02 +0000)
committerTed Kremenek <kremenek@apple.com>
Sat, 20 Mar 2010 18:02:01 +0000 (18:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99064 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Checker/BugReporter/BugReporter.h
lib/Checker/BugReporter.cpp
lib/Checker/BugReporterVisitors.cpp

index 5cbd8ba255eadd16882ee9351493142afd5c96fa..2c15f2a405760f3859454b359c7cbc46f7010874 100644 (file)
@@ -472,6 +472,7 @@ 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
 
index f26d16120e931ba59aa7af15e3e186b3bc9dc6c6..d4b150294e617c68928f7cc48a9e26db1dd45057 100644 (file)
@@ -1628,7 +1628,9 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
   else
     return;
 
+  // Register node visitors.
   R->registerInitialVisitors(PDB, N);
+  bugreporter::registerNilReceiverVisitor(PDB);
 
   switch (PDB.getGenerationScheme()) {
     case PathDiagnosticClient::Extensive:
index 7104f91d882ff374529c0f466964c6a5baaee6b6..1d6994b94b4b4d6bac4ad822fc5a8fd7458e798a 100644 (file)
@@ -379,3 +379,52 @@ void clang::bugreporter::registerFindLastStore(BugReporterContext& BRC,
 
   BRC.addVisitor(new FindLastStoreBRVisitor(V, R));
 }
+
+
+namespace {
+class NilReceiverVisitor : public BugReporterVisitor {
+public:
+  NilReceiverVisitor() {}
+
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    static int x = 0;
+    ID.AddPointer(&x);
+  }
+
+  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());
+}