r247590 - [Static Analyzer] Moving nullability checkers to a top level package.

Gabor Horvath via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 14 11:31:34 PDT 2015


Author: xazax
Date: Mon Sep 14 13:31:34 2015
New Revision: 247590

URL: http://llvm.org/viewvc/llvm-project?rev=247590&view=rev
Log:
[Static Analyzer] Moving nullability checkers to a top level package.

Differential Revision: http://reviews.llvm.org/D12852


Added:
    cfe/trunk/test/Analysis/nullability_nullonly.mm
Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
    cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
    cfe/trunk/test/Analysis/nullability.mm

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td?rev=247590&r1=247589&r2=247590&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td Mon Sep 14 13:31:34 2015
@@ -19,7 +19,7 @@ def Core : Package<"core">;
 def CoreBuiltin : Package<"builtin">, InPackage<Core>;
 def CoreUninitialized  : Package<"uninitialized">, InPackage<Core>;
 def CoreAlpha : Package<"core">, InPackage<Alpha>, Hidden;
-def Nullability : Package<"nullability">, InPackage<CoreAlpha>, Hidden;
+def Nullability : Package<"nullability">, InPackage<Alpha>, Hidden;
 
 def Cplusplus : Package<"cplusplus">;
 def CplusplusAlpha : Package<"cplusplus">, InPackage<Alpha>, Hidden;
@@ -153,7 +153,7 @@ def NullableReturnedFromNonnullChecker :
   HelpText<"Warns when a nullable pointer is returned from a function that has _Nonnull return type.">,
   DescFile<"NullabilityChecker.cpp">;
 
-} // end "alpha.core.nullability"
+} // end "alpha.nullability"
 
 //===----------------------------------------------------------------------===//
 // Evaluate "builtin" functions.

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp?rev=247590&r1=247589&r2=247590&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp Mon Sep 14 13:31:34 2015
@@ -136,6 +136,11 @@ public:
   };
 
   NullabilityChecksFilter Filter;
+  // When set to false no nullability information will be tracked in
+  // NullabilityMap. It is possible to catch errors like passing a null pointer
+  // to a callee that expects nonnull argument without the information that is
+  // stroed in the NullabilityMap. This is an optimization.
+  DefaultBool NeedTracking;
 
 private:
   class NullabilityBugVisitor
@@ -188,6 +193,11 @@ private:
     }
     BR.emitReport(std::move(R));
   }
+
+  /// If an SVal wraps a region that should be tracked, it will return a pointer
+  /// to the wrapped region. Otherwise it will return a nullptr.
+  const SymbolicRegion *getTrackRegion(SVal Val,
+                                       bool CheckSuperRegion = false) const;
 };
 
 class NullabilityState {
@@ -246,10 +256,11 @@ static NullConstraint getNullConstraint(
   return NullConstraint::Unknown;
 }
 
-// If an SVal wraps a region that should be tracked, it will return a pointer
-// to the wrapped region. Otherwise it will return a nullptr.
-static const SymbolicRegion *getTrackRegion(SVal Val,
-                                            bool CheckSuperRegion = false) {
+const SymbolicRegion *
+NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
+  if (!NeedTracking)
+    return nullptr;
+
   auto RegionSVal = Val.getAs<loc::MemRegionVal>();
   if (!RegionSVal)
     return nullptr;
@@ -941,15 +952,21 @@ void NullabilityChecker::printState(raw_
   }
 }
 
-#define REGISTER_CHECKER(name)                                                 \
+#define REGISTER_CHECKER(name, trackingRequired)                               \
   void ento::register##name##Checker(CheckerManager &mgr) {                    \
     NullabilityChecker *checker = mgr.registerChecker<NullabilityChecker>();   \
     checker->Filter.Check##name = true;                                        \
     checker->Filter.CheckName##name = mgr.getCurrentCheckName();               \
+    checker->NeedTracking = checker->NeedTracking || trackingRequired;         \
   }
 
-REGISTER_CHECKER(NullPassedToNonnull)
-REGISTER_CHECKER(NullReturnedFromNonnull)
-REGISTER_CHECKER(NullableDereferenced)
-REGISTER_CHECKER(NullablePassedToNonnull)
-REGISTER_CHECKER(NullableReturnedFromNonnull)
+// The checks are likely to be turned on by default and it is possible to do
+// them without tracking any nullability related information. As an optimization
+// no nullability information will be tracked when only these two checks are
+// enables.
+REGISTER_CHECKER(NullPassedToNonnull, false)
+REGISTER_CHECKER(NullReturnedFromNonnull, false)
+
+REGISTER_CHECKER(NullableDereferenced, true)
+REGISTER_CHECKER(NullablePassedToNonnull, true)
+REGISTER_CHECKER(NullableReturnedFromNonnull, true)

Modified: cfe/trunk/test/Analysis/nullability.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/nullability.mm?rev=247590&r1=247589&r2=247590&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/nullability.mm (original)
+++ cfe/trunk/test/Analysis/nullability.mm Mon Sep 14 13:31:34 2015
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.nullability -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.nullability -verify %s
 
 #define nil 0
 #define BOOL int

Added: cfe/trunk/test/Analysis/nullability_nullonly.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/nullability_nullonly.mm?rev=247590&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/nullability_nullonly.mm (added)
+++ cfe/trunk/test/Analysis/nullability_nullonly.mm Mon Sep 14 13:31:34 2015
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.nullability.NullPassedToNonnull,alpha.nullability.NullReturnedFromNonnull -verify %s
+
+int getRandom();
+
+typedef struct Dummy { int val; } Dummy;
+
+void takesNullable(Dummy *_Nullable);
+void takesNonnull(Dummy *_Nonnull);
+Dummy *_Nullable returnsNullable();
+
+void testBasicRules() {
+  // The tracking of nullable values is turned off.
+  Dummy *p = returnsNullable();
+  takesNonnull(p); // no warning
+  Dummy *q = 0;
+  if (getRandom()) {
+    takesNullable(q);
+    takesNonnull(q); // expected-warning {{}}
+  }
+}
+
+Dummy *_Nonnull testNullReturn() {
+  Dummy *p = 0;
+  return p; // expected-warning {{}}
+}
+
+void onlyReportFirstPreconditionViolationOnPath() {
+  Dummy *p = 0;
+  takesNonnull(p); // expected-warning {{}}
+  takesNonnull(p); // No warning.
+  // Passing null to nonnull is a sink. Stop the analysis.
+  int i = 0;
+  i = 5 / i; // no warning
+  (void)i;
+}
+
+Dummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc(
+    Dummy *_Nonnull p) {
+  if (!p) {
+    Dummy *ret =
+        0; // avoid compiler warning (which is not generated by the analyzer)
+    if (getRandom())
+      return ret; // no warning
+    else
+      return p; // no warning
+  } else {
+    return p;
+  }
+}
+
+Dummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) {
+  if (!p) {
+    Dummy *ret =
+        0; // avoid compiler warning (which is not generated by the analyzer)
+    if (getRandom())
+      return ret; // no warning
+    else
+      return p; // no warning
+  } else {
+    return p;
+  }
+}
+
+void testPreconditionViolationInInlinedFunction(Dummy *p) {
+  doNotWarnWhenPreconditionIsViolated(p);
+}
+
+void inlinedNullable(Dummy *_Nullable p) {
+  if (p) return;
+}
+void inlinedNonnull(Dummy *_Nonnull p) {
+  if (p) return;
+}
+void inlinedUnspecified(Dummy *p) {
+  if (p) return;
+}
+
+Dummy *_Nonnull testDefensiveInlineChecks(Dummy * p) {
+  switch (getRandom()) {
+  case 1: inlinedNullable(p); break;
+  case 2: inlinedNonnull(p); break;
+  case 3: inlinedUnspecified(p); break;
+  }
+  if (getRandom())
+    takesNonnull(p);
+  return p;
+}




More information about the cfe-commits mailing list