summaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:04:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:04:05 +0000
commit676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch)
tree02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
parentc7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff)
Notes
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp42
1 files changed, 24 insertions, 18 deletions
diff --git a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index 7d1ca61c97a9c..e535d1ae27ac5 100644
--- a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -25,7 +25,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -139,7 +139,6 @@ private:
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) override;
@@ -175,7 +174,8 @@ private:
if (Error == ErrorKind::NilAssignedToNonnull ||
Error == ErrorKind::NilPassedToNonnull ||
Error == ErrorKind::NilReturnedToNonnull)
- bugreporter::trackNullOrUndefValue(N, ValueExpr, *R);
+ if (const auto *Ex = dyn_cast<Expr>(ValueExpr))
+ bugreporter::trackExpressionValue(N, Ex, *R);
}
BR.emitReport(std::move(R));
}
@@ -185,7 +185,7 @@ private:
const SymbolicRegion *getTrackRegion(SVal Val,
bool CheckSuperRegion = false) const;
- /// Returns true if the call is diagnosable in the currrent analyzer
+ /// Returns true if the call is diagnosable in the current analyzer
/// configuration.
bool isDiagnosableCall(const CallEvent &Call) const {
if (NoDiagnoseCallsToSystemHeaders && Call.isInSystemHeader())
@@ -293,11 +293,10 @@ NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
std::shared_ptr<PathDiagnosticPiece>
NullabilityChecker::NullabilityBugVisitor::VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
BugReporterContext &BRC,
BugReport &BR) {
ProgramStateRef State = N->getState();
- ProgramStateRef StatePrev = PrevN->getState();
+ ProgramStateRef StatePrev = N->getFirstPred()->getState();
const NullabilityState *TrackedNullab = State->get<NullabilityMap>(Region);
const NullabilityState *TrackedNullabPrev =
@@ -311,7 +310,7 @@ NullabilityChecker::NullabilityBugVisitor::VisitNode(const ExplodedNode *N,
// Retrieve the associated statement.
const Stmt *S = TrackedNullab->getNullabilitySource();
- if (!S || S->getLocStart().isInvalid()) {
+ if (!S || S->getBeginLoc().isInvalid()) {
S = PathDiagnosticLocation::getStmt(N);
}
@@ -330,8 +329,8 @@ NullabilityChecker::NullabilityBugVisitor::VisitNode(const ExplodedNode *N,
nullptr);
}
-/// Returns true when the value stored at the given location is null
-/// and the passed in type is nonnnull.
+/// Returns true when the value stored at the given location has been
+/// constrained to null after being passed through an object of nonnnull type.
static bool checkValueAtLValForInvariantViolation(ProgramStateRef State,
SVal LV, QualType T) {
if (getNullabilityAnnotation(T) != Nullability::Nonnull)
@@ -341,9 +340,14 @@ static bool checkValueAtLValForInvariantViolation(ProgramStateRef State,
if (!RegionVal)
return false;
- auto StoredVal =
- State->getSVal(RegionVal->getRegion()).getAs<DefinedOrUnknownSVal>();
- if (!StoredVal)
+ // If the value was constrained to null *after* it was passed through that
+ // location, it could not have been a concrete pointer *when* it was passed.
+ // In that case we would have handled the situation when the value was
+ // bound to that location, by emitting (or not emitting) a report.
+ // Therefore we are only interested in symbolic regions that can be either
+ // null or non-null depending on the value of their respective symbol.
+ auto StoredVal = State->getSVal(*RegionVal).getAs<loc::MemRegionVal>();
+ if (!StoredVal || !isa<SymbolicRegion>(StoredVal->getRegion()))
return false;
if (getNullConstraint(*StoredVal, State) == NullConstraint::IsNull)
@@ -447,9 +451,6 @@ void NullabilityChecker::reportBugIfInvariantHolds(StringRef Msg,
/// Cleaning up the program state.
void NullabilityChecker::checkDeadSymbols(SymbolReaper &SR,
CheckerContext &C) const {
- if (!SR.hasDeadSymbols())
- return;
-
ProgramStateRef State = C.getState();
NullabilityMapTy Nullabilities = State->get<NullabilityMap>();
for (NullabilityMapTy::iterator I = Nullabilities.begin(),
@@ -766,7 +767,7 @@ void NullabilityChecker::checkPostCall(const CallEvent &Call,
// CG headers are misannotated. Do not warn for symbols that are the results
// of CG calls.
const SourceManager &SM = C.getSourceManager();
- StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getLocStart()));
+ StringRef FilePath = SM.getFilename(SM.getSpellingLoc(Decl->getBeginLoc()));
if (llvm::sys::path::filename(FilePath).startswith("CG")) {
State = State->set<NullabilityMap>(Region, Nullability::Contradicted);
C.addTransition(State);
@@ -1174,10 +1175,15 @@ void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
NullabilityMapTy B = State->get<NullabilityMap>();
+ if (State->get<InvariantViolated>())
+ Out << Sep << NL
+ << "Nullability invariant was violated, warnings suppressed." << NL;
+
if (B.isEmpty())
return;
- Out << Sep << NL;
+ if (!State->get<InvariantViolated>())
+ Out << Sep << NL;
for (NullabilityMapTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
Out << I->first << " : ";
@@ -1194,7 +1200,7 @@ void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
checker->NeedTracking = checker->NeedTracking || trackingRequired; \
checker->NoDiagnoseCallsToSystemHeaders = \
checker->NoDiagnoseCallsToSystemHeaders || \
- mgr.getAnalyzerOptions().getBooleanOption( \
+ mgr.getAnalyzerOptions().getCheckerBooleanOption( \
"NoDiagnoseCallsToSystemHeaders", false, checker, true); \
}