xazax.hun created this revision.
xazax.hun added reviewers: zaks.anna, krememek, jordan_rose, dcoughlin.
xazax.hun added a subscriber: cfe-commits.

For most of the implicit null pointer dereferences (when a pointer is 
dereferenced and the static analyzer can not prove that the pointer is non 
null, and can not prove that the pointer is null either) the DereferenceChecker 
will emit an event. However in some cases (e.g. binding such pointers to 
references in function parameters) no event will be emitted. This patch 
addresses this problem by extending NonNullParamChecker to emit an event in 
such cases. Future checkers (listening to these events) will profit from this 
change. For example I am working on a checker for nullability qualifiers that 
depend on this patch.

http://reviews.llvm.org/D11433

Files:
  lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp

Index: lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -28,7 +28,7 @@
 
 namespace {
 class NonNullParamChecker
-  : public Checker< check::PreCall > {
+  : public Checker< check::PreCall, EventDispatcher<ImplicitNullDerefEvent> > {
   mutable std::unique_ptr<BugType> BTAttrNonNull;
   mutable std::unique_ptr<BugType> BTNullRefArg;
 
@@ -139,26 +139,32 @@
     ProgramStateRef stateNotNull, stateNull;
     std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
 
-    if (stateNull && !stateNotNull) {
-      // Generate an error node.  Check for a null node in case
-      // we cache out.
-      if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
+    if (stateNull) {
+      if (!stateNotNull){
+        // Generate an error node.  Check for a null node in case
+        // we cache out.
+        if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
 
-        std::unique_ptr<BugReport> R;
-        if (haveAttrNonNull)
-          R = genReportNullAttrNonNull(errorNode, ArgE);
-        else if (haveRefTypeParam)
-          R = genReportReferenceToNullPointer(errorNode, ArgE);
+          std::unique_ptr<BugReport> R;
+          if (haveAttrNonNull)
+            R = genReportNullAttrNonNull(errorNode, ArgE);
+          else if (haveRefTypeParam)
+            R = genReportReferenceToNullPointer(errorNode, ArgE);
 
-        // Highlight the range of the argument that was null.
-        R->addRange(Call.getArgSourceRange(idx));
+          // Highlight the range of the argument that was null.
+          R->addRange(Call.getArgSourceRange(idx));
 
-        // Emit the bug report.
-        C.emitReport(std::move(R));
-      }
+          // Emit the bug report.
+          C.emitReport(std::move(R));
+        }
 
-      // Always return.  Either we cached out or we just emitted an error.
-      return;
+        // Always return.  Either we cached out or we just emitted an error.
+        return;
+      }
+      if (ExplodedNode *N = C.generateSink(stateNull)) {
+        ImplicitNullDerefEvent event = { V, false, N, &C.getBugReporter() };
+        dispatchEvent(event);
+      }
     }
 
     // If a pointer value passed the check we should assume that it is


Index: lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -28,7 +28,7 @@
 
 namespace {
 class NonNullParamChecker
-  : public Checker< check::PreCall > {
+  : public Checker< check::PreCall, EventDispatcher<ImplicitNullDerefEvent> > {
   mutable std::unique_ptr<BugType> BTAttrNonNull;
   mutable std::unique_ptr<BugType> BTNullRefArg;
 
@@ -139,26 +139,32 @@
     ProgramStateRef stateNotNull, stateNull;
     std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV);
 
-    if (stateNull && !stateNotNull) {
-      // Generate an error node.  Check for a null node in case
-      // we cache out.
-      if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
+    if (stateNull) {
+      if (!stateNotNull){
+        // Generate an error node.  Check for a null node in case
+        // we cache out.
+        if (ExplodedNode *errorNode = C.generateSink(stateNull)) {
 
-        std::unique_ptr<BugReport> R;
-        if (haveAttrNonNull)
-          R = genReportNullAttrNonNull(errorNode, ArgE);
-        else if (haveRefTypeParam)
-          R = genReportReferenceToNullPointer(errorNode, ArgE);
+          std::unique_ptr<BugReport> R;
+          if (haveAttrNonNull)
+            R = genReportNullAttrNonNull(errorNode, ArgE);
+          else if (haveRefTypeParam)
+            R = genReportReferenceToNullPointer(errorNode, ArgE);
 
-        // Highlight the range of the argument that was null.
-        R->addRange(Call.getArgSourceRange(idx));
+          // Highlight the range of the argument that was null.
+          R->addRange(Call.getArgSourceRange(idx));
 
-        // Emit the bug report.
-        C.emitReport(std::move(R));
-      }
+          // Emit the bug report.
+          C.emitReport(std::move(R));
+        }
 
-      // Always return.  Either we cached out or we just emitted an error.
-      return;
+        // Always return.  Either we cached out or we just emitted an error.
+        return;
+      }
+      if (ExplodedNode *N = C.generateSink(stateNull)) {
+        ImplicitNullDerefEvent event = { V, false, N, &C.getBugReporter() };
+        dispatchEvent(event);
+      }
     }
 
     // If a pointer value passed the check we should assume that it is
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to