tripleCC updated this revision to Diff 529116. tripleCC added a comment. [StaticAnalyzer] add might be null test case for NilArgChecker
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D152269/new/ https://reviews.llvm.org/D152269 Files: clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp clang/test/Analysis/NSContainers.m Index: clang/test/Analysis/NSContainers.m =================================================================== --- clang/test/Analysis/NSContainers.m +++ clang/test/Analysis/NSContainers.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -Wno-objc-literal-conversion -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops,debug.ExprInspection -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -Wno-objc-literal-conversion -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops,debug.ExprInspection,nullability -verify -Wno-objc-root-class %s void clang_analyzer_eval(int); @@ -323,3 +323,19 @@ // that 'obj' can be nil in this context. dict[obj] = getStringFromString(obj); // no-warning } + +Foo * _Nonnull getNonnullFoo(); +Foo * _Nullable getNullableFoo(); +Foo * getMightBeNullFoo(); + +void testCreateDictionaryLiteralWithNullableArg() { + (void)@{@"abc" : getMightBeNullFoo()}; // no warning + (void)@{@"abc" : getNonnullFoo()}; // no warning + (void)@{@"abc" : getNullableFoo()}; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null}} +} + +void testCreateArrayLiteralWithNullableArg() { + (void)@[getMightBeNullFoo()]; // no warning + (void)@[getNonnullFoo()]; // no warning + (void)@[getNullableFoo()]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null}} +} Index: clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -97,7 +97,8 @@ namespace { class NilArgChecker : public Checker<check::PreObjCMessage, check::PostStmt<ObjCDictionaryLiteral>, - check::PostStmt<ObjCArrayLiteral> > { + check::PostStmt<ObjCArrayLiteral>, + EventDispatcher<ImplicitNullDerefEvent>> { mutable std::unique_ptr<APIMisuse> BT; mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors; @@ -141,11 +142,31 @@ CheckerContext &C) const { ProgramStateRef State = C.getState(); if (State->isNull(C.getSVal(E)).isConstrainedTrue()) { - if (ExplodedNode *N = C.generateErrorNode()) { generateBugReport(N, Msg, E->getSourceRange(), E, C); + return; } } + + auto ArgSVal = C.getSVal(E).getAs<DefinedOrUnknownSVal>(); + if (!ArgSVal) + return; + + ProgramStateRef StNonNull, StNull; + std::tie(StNonNull, StNull) = State->assume(*ArgSVal); + + if (StNull) { + if (ExplodedNode *N = C.generateSink(StNull, C.getPredecessor())) { + ImplicitNullDerefEvent event = {*ArgSVal, false, N, &C.getBugReporter(), + /*IsDirectDereference=*/false}; + dispatchEvent(event); + } + } + + if (StNonNull) + State = StNonNull; + + C.addTransition(State); } void NilArgChecker::warnIfNilArg(CheckerContext &C,
Index: clang/test/Analysis/NSContainers.m =================================================================== --- clang/test/Analysis/NSContainers.m +++ clang/test/Analysis/NSContainers.m @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -Wno-objc-literal-conversion -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops,debug.ExprInspection -verify -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -Wno-objc-literal-conversion -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops,debug.ExprInspection,nullability -verify -Wno-objc-root-class %s void clang_analyzer_eval(int); @@ -323,3 +323,19 @@ // that 'obj' can be nil in this context. dict[obj] = getStringFromString(obj); // no-warning } + +Foo * _Nonnull getNonnullFoo(); +Foo * _Nullable getNullableFoo(); +Foo * getMightBeNullFoo(); + +void testCreateDictionaryLiteralWithNullableArg() { + (void)@{@"abc" : getMightBeNullFoo()}; // no warning + (void)@{@"abc" : getNonnullFoo()}; // no warning + (void)@{@"abc" : getNullableFoo()}; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null}} +} + +void testCreateArrayLiteralWithNullableArg() { + (void)@[getMightBeNullFoo()]; // no warning + (void)@[getNonnullFoo()]; // no warning + (void)@[getNullableFoo()]; // expected-warning {{Nullable pointer is passed to a callee that requires a non-null}} +} Index: clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -97,7 +97,8 @@ namespace { class NilArgChecker : public Checker<check::PreObjCMessage, check::PostStmt<ObjCDictionaryLiteral>, - check::PostStmt<ObjCArrayLiteral> > { + check::PostStmt<ObjCArrayLiteral>, + EventDispatcher<ImplicitNullDerefEvent>> { mutable std::unique_ptr<APIMisuse> BT; mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors; @@ -141,11 +142,31 @@ CheckerContext &C) const { ProgramStateRef State = C.getState(); if (State->isNull(C.getSVal(E)).isConstrainedTrue()) { - if (ExplodedNode *N = C.generateErrorNode()) { generateBugReport(N, Msg, E->getSourceRange(), E, C); + return; } } + + auto ArgSVal = C.getSVal(E).getAs<DefinedOrUnknownSVal>(); + if (!ArgSVal) + return; + + ProgramStateRef StNonNull, StNull; + std::tie(StNonNull, StNull) = State->assume(*ArgSVal); + + if (StNull) { + if (ExplodedNode *N = C.generateSink(StNull, C.getPredecessor())) { + ImplicitNullDerefEvent event = {*ArgSVal, false, N, &C.getBugReporter(), + /*IsDirectDereference=*/false}; + dispatchEvent(event); + } + } + + if (StNonNull) + State = StNonNull; + + C.addTransition(State); } void NilArgChecker::warnIfNilArg(CheckerContext &C,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits