diff options
| author | Jordan Rose <jordan_rose@apple.com> | 2014-02-08 00:04:14 +0000 |
|---|---|---|
| committer | Jordan Rose <jordan_rose@apple.com> | 2014-02-08 00:04:14 +0000 |
| commit | 4393aa7efb0829f463911f783d87e8a9f039ffbd (patch) | |
| tree | 6f381ea92e2495d3c60cde1daef1f23833e96a7a | |
| parent | b3b52a753207f1d910fce17f9b354141e8e28fd7 (diff) | |
| download | bcm5719-llvm-4393aa7efb0829f463911f783d87e8a9f039ffbd.tar.gz bcm5719-llvm-4393aa7efb0829f463911f783d87e8a9f039ffbd.zip | |
[analyzer] Objective-C object literals are always non-nil.
<rdar://problem/15999214>
llvm-svn: 201007
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp | 30 | ||||
| -rw-r--r-- | clang/test/Analysis/NSContainers.m | 10 | ||||
| -rw-r--r-- | clang/test/Analysis/objc-boxing.m | 17 |
3 files changed, 50 insertions, 7 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 3384d4bc066..adf1b239421 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -1139,7 +1139,10 @@ namespace { /// \brief The checker restricts the return values of APIs known to /// never (or almost never) return 'nil'. class ObjCNonNilReturnValueChecker - : public Checker<check::PostObjCMessage> { + : public Checker<check::PostObjCMessage, + check::PostStmt<ObjCArrayLiteral>, + check::PostStmt<ObjCDictionaryLiteral>, + check::PostStmt<ObjCBoxedExpr> > { mutable bool Initialized; mutable Selector ObjectAtIndex; mutable Selector ObjectAtIndexedSubscript; @@ -1147,13 +1150,32 @@ class ObjCNonNilReturnValueChecker public: ObjCNonNilReturnValueChecker() : Initialized(false) {} + + ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr, + ProgramStateRef State, + CheckerContext &C) const; + void assumeExprIsNonNull(const Expr *E, CheckerContext &C) const { + C.addTransition(assumeExprIsNonNull(E, C.getState(), C)); + } + + void checkPostStmt(const ObjCArrayLiteral *E, CheckerContext &C) const { + assumeExprIsNonNull(E, C); + } + void checkPostStmt(const ObjCDictionaryLiteral *E, CheckerContext &C) const { + assumeExprIsNonNull(E, C); + } + void checkPostStmt(const ObjCBoxedExpr *E, CheckerContext &C) const { + assumeExprIsNonNull(E, C); + } + void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const; }; } -static ProgramStateRef assumeExprIsNonNull(const Expr *NonNullExpr, - ProgramStateRef State, - CheckerContext &C) { +ProgramStateRef +ObjCNonNilReturnValueChecker::assumeExprIsNonNull(const Expr *NonNullExpr, + ProgramStateRef State, + CheckerContext &C) const { SVal Val = State->getSVal(NonNullExpr, C.getLocationContext()); if (Optional<DefinedOrUnknownSVal> DV = Val.getAs<DefinedOrUnknownSVal>()) return State->assume(*DV, true); diff --git a/clang/test/Analysis/NSContainers.m b/clang/test/Analysis/NSContainers.m index a9e76fbbcab..3d3603acb34 100644 --- a/clang/test/Analysis/NSContainers.m +++ b/clang/test/Analysis/NSContainers.m @@ -1,4 +1,7 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops -verify -Wno-objc-root-class %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops,debug.ExprInspection -verify -Wno-objc-root-class %s + +void clang_analyzer_eval(int); + typedef unsigned long NSUInteger; typedef signed char BOOL; typedef struct _NSZone NSZone; @@ -276,3 +279,8 @@ void testCountAwareNSOrderedSet(NSOrderedSet *containers, int *validptr) { } } +void testLiteralsNonNil() { + clang_analyzer_eval(!!@[]); // expected-warning{{TRUE}} + clang_analyzer_eval(!!@{}); // expected-warning{{TRUE}} +} + diff --git a/clang/test/Analysis/objc-boxing.m b/clang/test/Analysis/objc-boxing.m index 98310b52f49..c23192e17e5 100644 --- a/clang/test/Analysis/objc-boxing.m +++ b/clang/test/Analysis/objc-boxing.m @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,osx.cocoa.NonNilReturnValue,debug.ExprInspection -analyzer-store=region -verify %s + +void clang_analyzer_eval(int); typedef signed char BOOL; typedef long NSInteger; @@ -41,4 +43,15 @@ id const_char_pointer(int *x) { if (x) return @(3); return @(*x); // expected-warning {{Dereference of null pointer (loaded from variable 'x')}} -}
\ No newline at end of file +} + +void checkNonNil() { + clang_analyzer_eval(!!@3); // expected-warning{{TRUE}} + clang_analyzer_eval(!!@(3+4)); // expected-warning{{TRUE}} + clang_analyzer_eval(!!@(57.0)); // expected-warning{{TRUE}} + + const char *str = "abc"; + clang_analyzer_eval(!!@(str)); // expected-warning{{TRUE}} + clang_analyzer_eval(!!@__objc_yes); // expected-warning{{TRUE}} +} + |

