FC_NSArray,
FC_NSDictionary,
FC_NSEnumerator,
+ FC_NSNull,
FC_NSOrderedSet,
FC_NSSet,
FC_NSString
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;
mutable bool Initialized;
mutable Selector ObjectAtIndex;
mutable Selector ObjectAtIndexedSubscript;
+ mutable Selector NullSelector;
public:
ObjCNonNilReturnValueChecker() : Initialized(false) {}
ASTContext &Ctx = C.getASTContext();
ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
+ NullSelector = GetNullarySelector("null", Ctx);
}
// Check the receiver type.
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) {
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);
}
-// 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;
@end
+@interface NSNull : NSObject <NSCopying, NSSecureCoding>
++ (NSNull *)null;
+@end
+
// NSMutableArray API
void testNilArgNSMutableArray1() {
NSMutableArray *marray = [[NSMutableArray alloc] init];
[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
+ }
+}
+