r246182 - [Static Analyzer] Make NonNullParamChecker emit implicit null dereference events.
Gabor Horvath via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 27 11:49:07 PDT 2015
Author: xazax
Date: Thu Aug 27 13:49:07 2015
New Revision: 246182
URL: http://llvm.org/viewvc/llvm-project?rev=246182&view=rev
Log:
[Static Analyzer] Make NonNullParamChecker emit implicit null dereference events.
Differential Revision: http://reviews.llvm.org/D11433
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h
cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
cfe/trunk/test/Analysis/nullability.mm
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h?rev=246182&r1=246181&r2=246182&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h Thu Aug 27 13:49:07 2015
@@ -514,6 +514,10 @@ struct ImplicitNullDerefEvent {
bool IsLoad;
ExplodedNode *SinkNode;
BugReporter *BR;
+ // When true, the dereference is in the source code directly. When false, the
+ // dereference might happen later (for example pointer passed to a parameter
+ // that is marked with nonnull attribute.)
+ bool IsDirectDereference;
};
/// \brief A helper class which wraps a boolean value set to false by default.
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp?rev=246182&r1=246181&r2=246182&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp Thu Aug 27 13:49:07 2015
@@ -220,7 +220,8 @@ void DereferenceChecker::checkLocation(S
// null or not-null. Record the error node as an "implicit" null
// dereference.
if (ExplodedNode *N = C.generateSink(nullState)) {
- ImplicitNullDerefEvent event = { l, isLoad, N, &C.getBugReporter() };
+ ImplicitNullDerefEvent event = {l, isLoad, N, &C.getBugReporter(),
+ /*IsDirectDereference=*/false};
dispatchEvent(event);
}
}
@@ -257,8 +258,9 @@ void DereferenceChecker::checkBind(SVal
// At this point the value could be either null or non-null.
// Record this as an "implicit" null dereference.
if (ExplodedNode *N = C.generateSink(StNull)) {
- ImplicitNullDerefEvent event = { V, /*isLoad=*/true, N,
- &C.getBugReporter() };
+ ImplicitNullDerefEvent event = {V, /*isLoad=*/true, N,
+ &C.getBugReporter(),
+ /*IsDirectDereference=*/false};
dispatchEvent(event);
}
}
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp?rev=246182&r1=246181&r2=246182&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp Thu Aug 27 13:49:07 2015
@@ -28,7 +28,7 @@ using namespace ento;
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,34 @@ void NonNullParamChecker::checkPreCall(c
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)) {
-
- std::unique_ptr<BugReport> R;
- if (haveAttrNonNull)
- R = genReportNullAttrNonNull(errorNode, ArgE);
- else if (haveRefTypeParam)
- R = genReportReferenceToNullPointer(errorNode, ArgE);
+ 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);
+
+ // Highlight the range of the argument that was null.
+ R->addRange(Call.getArgSourceRange(idx));
+
+ // Emit the bug report.
+ C.emitReport(std::move(R));
+ }
- // Highlight the range of the argument that was null.
- R->addRange(Call.getArgSourceRange(idx));
-
- // Emit the bug report.
- C.emitReport(std::move(R));
+ // 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(),
+ /*IsDirectDereference=*/haveRefTypeParam};
+ dispatchEvent(event);
}
-
- // Always return. Either we cached out or we just emitted an error.
- return;
}
// If a pointer value passed the check we should assume that it is
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp?rev=246182&r1=246181&r2=246182&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp Thu Aug 27 13:49:07 2015
@@ -335,7 +335,10 @@ void NullabilityChecker::checkEvent(Impl
if (Filter.CheckNullableDereferenced &&
TrackedNullability->getValue() == Nullability::Nullable) {
BugReporter &BR = *Event.BR;
- reportBug(ErrorKind::NullableDereferenced, Event.SinkNode, Region, BR);
+ if (Event.IsDirectDereference)
+ reportBug(ErrorKind::NullableDereferenced, Event.SinkNode, Region, BR);
+ else
+ reportBug(ErrorKind::NullablePassedToNonnull, Event.SinkNode, Region, BR);
}
}
Modified: cfe/trunk/test/Analysis/nullability.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/nullability.mm?rev=246182&r1=246181&r2=246182&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/nullability.mm (original)
+++ cfe/trunk/test/Analysis/nullability.mm Thu Aug 27 13:49:07 2015
@@ -50,6 +50,8 @@ int *_Nullable returnsNullableInt();
template <typename T> T *eraseNullab(T *p) { return p; }
+void takesAttrNonnull(Dummy *p) __attribute((nonnull(1)));
+
void testBasicRules() {
Dummy *p = returnsNullable();
int *ptr = returnsNullableInt();
@@ -73,10 +75,8 @@ void testBasicRules() {
Dummy dd(d);
break;
}
- // Here the copy constructor is called, so a reference is initialized with the
- // value of p. No ImplicitNullDereference event will be dispatched for this
- // case. A followup patch is expected to fix this in NonNullParamChecker.
- default: { Dummy d = *p; } break; // No warning.
+ case 5: takesAttrNonnull(p); break; // expected-warning {{Nullable pointer is passed to}}
+ default: { Dummy d = *p; } break; // expected-warning {{Nullable pointer is dereferenced}}
}
if (p) {
takesNonnull(p);
More information about the cfe-commits
mailing list