From a8695180217806bb421cfc6700bec76fc0b1ae56 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Sat, 4 Aug 2012 01:04:52 +0000 Subject: [PATCH] [analyzer] Use a more robust check for null in CallAndMessageChecker. This should fix the failing test on the buildbot as well. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161290 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/CallAndMessageChecker.cpp | 14 ++++++++++++-- test/Analysis/misc-ps-region-store.cpp | 8 ++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index e09d6885a9..30f45c7685 100644 --- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -232,7 +232,11 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE, return; } - if (L.isZeroConstant()) { + ProgramStateRef StNonNull, StNull; + llvm::tie(StNonNull, StNull) = State->assume(cast(L)); + + // FIXME: Do we want to record the non-null assumption here? + if (StNull && !StNonNull) { if (!BT_call_null) BT_call_null.reset( new BuiltinBug("Called function pointer is null (null dereference)")); @@ -253,7 +257,13 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call, emitBadCall(BT_cxx_call_undef.get(), C, CC->getCXXThisExpr()); return; } - if (V.isZeroConstant()) { + + ProgramStateRef State = C.getState(); + ProgramStateRef StNonNull, StNull; + llvm::tie(StNonNull, StNull) = State->assume(cast(V)); + + // FIXME: Do we want to record the non-null assumption here? + if (StNull && !StNonNull) { if (!BT_cxx_call_null) BT_cxx_call_null.reset(new BuiltinBug("Called C++ object pointer " "is null")); diff --git a/test/Analysis/misc-ps-region-store.cpp b/test/Analysis/misc-ps-region-store.cpp index fcffe07536..e30cedb911 100644 --- a/test/Analysis/misc-ps-region-store.cpp +++ b/test/Analysis/misc-ps-region-store.cpp @@ -272,11 +272,11 @@ const Rdar9212495_A& rdar9212495(const Rdar9212495_C* ptr) { const Rdar9212495_A& val = dynamic_cast(*ptr); // This is not valid C++; dynamic_cast with a reference type will throw an - // exception if the pointer does not match the expected type. + // exception if the pointer does not match the expected type. However, our + // implementation of dynamic_cast will pass through a null pointer...or a + // "null reference"! So this branch is actually possible. if (&val == 0) { - val.bar(); // no warning (unreachable) - int *p = 0; - *p = 0xDEAD; // no warning (unreachable) + val.bar(); // expected-warning{{Called C++ object pointer is null}} } return val; -- 2.40.0