r181616 - [analyzer] Assume [NSNull null] does not return nil.

Anna Zaks ganna at apple.com
Fri May 10 11:04:46 PDT 2013


Author: zaks
Date: Fri May 10 13:04:46 2013
New Revision: 181616

URL: http://llvm.org/viewvc/llvm-project?rev=181616&view=rev
Log:
[analyzer] Assume [NSNull null] does not return nil.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
    cfe/trunk/test/Analysis/NSContainers.m

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp?rev=181616&r1=181615&r2=181616&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp Fri May 10 13:04:46 2013
@@ -58,6 +58,7 @@ enum FoundationClass {
   FC_NSArray,
   FC_NSDictionary,
   FC_NSEnumerator,
+  FC_NSNull,
   FC_NSOrderedSet,
   FC_NSSet,
   FC_NSString
@@ -69,6 +70,7 @@ static FoundationClass findKnownClass(co
     Classes["NSArray"] = FC_NSArray;
     Classes["NSDictionary"] = FC_NSDictionary;
     Classes["NSEnumerator"] = FC_NSEnumerator;
+    Classes["NSNull"] = FC_NSNull;
     Classes["NSOrderedSet"] = FC_NSOrderedSet;
     Classes["NSSet"] = FC_NSSet;
     Classes["NSString"] = FC_NSString;
@@ -845,6 +847,7 @@ class ObjCNonNilReturnValueChecker
     mutable bool Initialized;
     mutable Selector ObjectAtIndex;
     mutable Selector ObjectAtIndexedSubscript;
+    mutable Selector NullSelector;
 
 public:
   ObjCNonNilReturnValueChecker() : Initialized(false) {}
@@ -870,6 +873,7 @@ void ObjCNonNilReturnValueChecker::check
     ASTContext &Ctx = C.getASTContext();
     ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
     ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
+    NullSelector = GetNullarySelector("null", Ctx);
   }
 
   // Check the receiver type.
@@ -889,16 +893,25 @@ void ObjCNonNilReturnValueChecker::check
       State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
     }
 
+    FoundationClass Cl = findKnownClass(Interface);
+
     // Objects returned from
     // [NSArray|NSOrderedSet]::[ObjectAtIndex|ObjectAtIndexedSubscript]
     // are never 'nil'.
-    FoundationClass Cl = findKnownClass(Interface);
     if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
       Selector Sel = M.getSelector();
       if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
         // Go ahead and assume the value is non-nil.
         State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
       }
+    }
+
+    // Objects returned from [NSNull null] are not nil.
+    if (Cl == FC_NSNull) {
+      if (M.getSelector() == NullSelector) {
+        // Go ahead and assume the value is non-nil.
+        State = assumeExprIsNonNull(M.getOriginExpr(), State, C);
+      }
     }
   }
   C.addTransition(State);

Modified: cfe/trunk/test/Analysis/NSContainers.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NSContainers.m?rev=181616&r1=181615&r2=181616&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/NSContainers.m (original)
+++ cfe/trunk/test/Analysis/NSContainers.m Fri May 10 13:04:46 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NilArg -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg -verify -Wno-objc-root-class %s
 typedef unsigned long NSUInteger;
 typedef signed char BOOL;
 typedef struct _NSZone NSZone;
@@ -81,6 +81,10 @@ typedef struct _NSZone NSZone;
 
 @end
 
+ at interface NSNull : NSObject <NSCopying, NSSecureCoding>
++ (NSNull *)null;
+ at end
+
 // NSMutableArray API
 void testNilArgNSMutableArray1() {
   NSMutableArray *marray = [[NSMutableArray alloc] init];
@@ -197,4 +201,13 @@ void testNilReceiverRetNil2(NSMutableDic
   [D setObject: value forKey: key]; // no-warning
 }
 
+void testAssumeNSNullNullReturnsNonNil(NSMutableDictionary *Table, id Object,
+                                      id InValue) {
+  id Value = Object ? [Table objectForKey:Object] : [NSNull null];
+  if (!Value) {
+    Value = InValue;
+    [Table setObject:Value forKey:Object]; // no warning
+  }
+}
+
 





More information about the cfe-commits mailing list