summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2014-02-08 00:04:14 +0000
committerJordan Rose <jordan_rose@apple.com>2014-02-08 00:04:14 +0000
commit4393aa7efb0829f463911f783d87e8a9f039ffbd (patch)
tree6f381ea92e2495d3c60cde1daef1f23833e96a7a
parentb3b52a753207f1d910fce17f9b354141e8e28fd7 (diff)
downloadbcm5719-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.cpp30
-rw-r--r--clang/test/Analysis/NSContainers.m10
-rw-r--r--clang/test/Analysis/objc-boxing.m17
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}}
+}
+
OpenPOWER on IntegriCloud