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