diff options
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp index a94d7a773e..e98c131ce9 100644 --- a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -233,7 +233,7 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S, void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S, CheckerContext &C) const { - // If we're binding to a reference, check if the value is potentially null. + // If we're binding to a reference, check if the value is known to be null. if (V.isUndef()) return; @@ -265,8 +265,23 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S, } } - // From here on out, assume the value is non-null. - C.addTransition(StNonNull); + // Unlike a regular null dereference, initializing a reference with a + // dereferenced null pointer does not actually cause a runtime exception in + // Clang's implementation of references. + // + // int &r = *p; // safe?? + // if (p != NULL) return; // uh-oh + // r = 5; // trap here + // + // The standard says this is invalid as soon as we try to create a "null + // reference" (there is no such thing), but turning this into an assumption + // that 'p' is never null will not match our actual runtime behavior. + // So we do not record this assumption, allowing us to warn on the last line + // of this example. + // + // We do need to add a transition because we may have generated a sink for + // the "implicit" null dereference. + C.addTransition(State, this); } void ento::registerDereferenceChecker(CheckerManager &mgr) { |