xazax.hun updated this revision to Diff 34705. xazax.hun added a comment. Removed an unintended comment formatting change.
http://reviews.llvm.org/D12852 Files: lib/StaticAnalyzer/Checkers/Checkers.td lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp test/Analysis/nullability.mm test/Analysis/nullability_nullonly.mm
Index: test/Analysis/nullability_nullonly.mm =================================================================== --- /dev/null +++ test/Analysis/nullability_nullonly.mm @@ -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; +} Index: test/Analysis/nullability.mm =================================================================== --- test/Analysis/nullability.mm +++ test/Analysis/nullability.mm @@ -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 Index: lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp +++ lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp @@ -136,6 +136,7 @@ }; NullabilityChecksFilter Filter; + DefaultBool NeedTracking; private: class NullabilityBugVisitor @@ -188,6 +189,11 @@ } 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 +252,11 @@ 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 +948,16 @@ } } -#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) +REGISTER_CHECKER(NullPassedToNonnull, false) +REGISTER_CHECKER(NullReturnedFromNonnull, false) +REGISTER_CHECKER(NullableDereferenced, true) +REGISTER_CHECKER(NullablePassedToNonnull, true) +REGISTER_CHECKER(NullableReturnedFromNonnull, true) Index: lib/StaticAnalyzer/Checkers/Checkers.td =================================================================== --- lib/StaticAnalyzer/Checkers/Checkers.td +++ lib/StaticAnalyzer/Checkers/Checkers.td @@ -19,7 +19,7 @@ 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 @@ 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.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits