chrisbazley created this revision. Herald added subscribers: steakhal, martong. Herald added a reviewer: NoQ. Herald added a project: All. chrisbazley requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Without this change, the following code does not generate "warning: Nullable pointer is dereferenced": void test(void (*_Nullable fn)(void)) { fn(); } Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D142742 Files: clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp Index: clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -32,7 +32,7 @@ class CallAndMessageChecker : public Checker<check::PreObjCMessage, check::ObjCMessageNil, - check::PreCall> { + check::PreCall, EventDispatcher<ImplicitNullDerefEvent>> { mutable std::unique_ptr<BugType> BT_call_null; mutable std::unique_ptr<BugType> BT_call_undef; mutable std::unique_ptr<BugType> BT_cxx_call_null; @@ -389,16 +389,30 @@ ProgramStateRef StNonNull, StNull; std::tie(StNonNull, StNull) = State->assume(L.castAs<DefinedOrUnknownSVal>()); - if (StNull && !StNonNull) { - if (!ChecksEnabled[CK_FunctionPointer]) { - C.addSink(StNull); + if (StNull) { + if (!StNonNull) { + if (!ChecksEnabled[CK_FunctionPointer]) { + C.addSink(StNull); + return nullptr; + } + if (!BT_call_null) + BT_call_null.reset(new BuiltinBug( + OriginalName, + "Called function pointer is null (null dereference)")); + emitBadCall(BT_call_null.get(), C, Callee); return nullptr; } - if (!BT_call_null) - BT_call_null.reset(new BuiltinBug( - OriginalName, "Called function pointer is null (null dereference)")); - emitBadCall(BT_call_null.get(), C, Callee); - return nullptr; + + // Otherwise, we have the case where the location could either be + // null or not-null. Record the error node as an "implicit" null + // dereference. + if (ExplodedNode *N = C.generateSink(StNull, C.getPredecessor())) { + printf("\nimplicit null dereference\n"); + ImplicitNullDerefEvent event = {L, /*isLoad=*/true, N, + &C.getBugReporter(), + /*IsDirectDereference=*/true}; + dispatchEvent(event); + } } return StNonNull;
Index: clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -32,7 +32,7 @@ class CallAndMessageChecker : public Checker<check::PreObjCMessage, check::ObjCMessageNil, - check::PreCall> { + check::PreCall, EventDispatcher<ImplicitNullDerefEvent>> { mutable std::unique_ptr<BugType> BT_call_null; mutable std::unique_ptr<BugType> BT_call_undef; mutable std::unique_ptr<BugType> BT_cxx_call_null; @@ -389,16 +389,30 @@ ProgramStateRef StNonNull, StNull; std::tie(StNonNull, StNull) = State->assume(L.castAs<DefinedOrUnknownSVal>()); - if (StNull && !StNonNull) { - if (!ChecksEnabled[CK_FunctionPointer]) { - C.addSink(StNull); + if (StNull) { + if (!StNonNull) { + if (!ChecksEnabled[CK_FunctionPointer]) { + C.addSink(StNull); + return nullptr; + } + if (!BT_call_null) + BT_call_null.reset(new BuiltinBug( + OriginalName, + "Called function pointer is null (null dereference)")); + emitBadCall(BT_call_null.get(), C, Callee); return nullptr; } - if (!BT_call_null) - BT_call_null.reset(new BuiltinBug( - OriginalName, "Called function pointer is null (null dereference)")); - emitBadCall(BT_call_null.get(), C, Callee); - return nullptr; + + // Otherwise, we have the case where the location could either be + // null or not-null. Record the error node as an "implicit" null + // dereference. + if (ExplodedNode *N = C.generateSink(StNull, C.getPredecessor())) { + printf("\nimplicit null dereference\n"); + ImplicitNullDerefEvent event = {L, /*isLoad=*/true, N, + &C.getBugReporter(), + /*IsDirectDereference=*/true}; + dispatchEvent(event); + } } return StNonNull;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits