blob: 66d27d3fcc06f31e821ff30e136c9284b1768ce3 [file] [log] [blame]
Dominic Chen184c6242017-03-03 18:02:02 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=text -analyzer-config suppress-null-return-paths=false -fblocks -verify %s
George Karpenkov39165092018-06-12 19:07:41 +00002// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount -analyzer-output=plist-multi-file -analyzer-config suppress-null-return-paths=false -fblocks %s -o %t.plist
Mikhail Maltsevc704f4d2018-09-17 10:19:46 +00003// RUN: cat %t.plist | %diff_plist %S/Inputs/expected-plists/path-notes.m.plist
Jordan Rose6f3d2f02012-09-22 01:24:49 +00004
Jordan Rose2d98b972012-11-15 02:07:23 +00005typedef struct dispatch_queue_s *dispatch_queue_t;
6typedef void (^dispatch_block_t)(void);
7void dispatch_sync(dispatch_queue_t, dispatch_block_t);
8
Jordan Rose5fbe7f92013-08-01 22:16:30 +00009typedef long dispatch_once_t;
10// Note: The real dispatch_once has all parameters marked nonnull.
11// We don't do that here so that we can trigger a null dereference inside
12// the synthesized body.
13void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
14
Jordan Rose2d98b972012-11-15 02:07:23 +000015
Jordan Rose6f3d2f02012-09-22 01:24:49 +000016@interface Test
17@property int *p;
18@end
19
Anna Zaks6afa8f12013-05-13 23:49:51 +000020typedef unsigned long NSUInteger;
21typedef signed char BOOL;
22typedef struct _NSZone NSZone;
23@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
24@protocol NSObject
25@end
26@protocol NSCopying
27- (id)copyWithZone:(NSZone *)zone;
28@end
29@protocol NSMutableCopying
30- (id)mutableCopyWithZone:(NSZone *)zone;
31@end
32@protocol NSCoding
33- (void)encodeWithCoder:(NSCoder *)aCoder;
34@end
35@protocol NSFastEnumeration
36@end
37@protocol NSSecureCoding <NSCoding>
38@required
39+ (BOOL)supportsSecureCoding;
40@end
41@interface NSObject <NSObject> {}
42- (id)init;
43+ (id)alloc;
Jordan Rose5fbe7f92013-08-01 22:16:30 +000044- (id)autorelease;
Anna Zaks6afa8f12013-05-13 23:49:51 +000045@end
46@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
47
48- (NSUInteger)count;
49- (id)objectAtIndex:(NSUInteger)index;
50
51@end
52
53@interface NSArray (NSExtendedArray)
54- (NSArray *)arrayByAddingObject:(id)anObject;
55- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8)));
56@end
57
58@interface NSArray (NSArrayCreation)
59+ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
60@end
61
62@interface NSMutableArray : NSArray
63
64- (void)addObject:(id)anObject;
65- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
66- (void)removeLastObject;
67- (void)removeObjectAtIndex:(NSUInteger)index;
68- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
69
70@end
71
Jordan Rose6f3d2f02012-09-22 01:24:49 +000072int *getZeroIfNil(Test *x) {
73 return x.p;
Ted Kremenekd51ad8c2013-04-18 17:44:15 +000074 // expected-note@-1 {{'p' not called because the receiver is nil}}
Jordan Rose6f3d2f02012-09-22 01:24:49 +000075 // expected-note@-2 {{Returning null pointer}}
76}
77
78void testReturnZeroIfNil() {
79 *getZeroIfNil(0) = 1; // expected-warning{{Dereference of null pointer}}
80 // expected-note@-1 {{Calling 'getZeroIfNil'}}
81 // expected-note@-2 {{Passing nil object reference via 1st parameter 'x'}}
82 // expected-note@-3 {{Returning from 'getZeroIfNil'}}
83 // expected-note@-4 {{Dereference of null pointer}}
84}
85
86
Jordan Rose2d98b972012-11-15 02:07:23 +000087int testDispatchSyncInlining() {
88 extern dispatch_queue_t globalQueue;
89
90 __block int x;
91
92 // expected-note@+2 {{Calling 'dispatch_sync'}}
93 // expected-note@+1 {{Returning from 'dispatch_sync'}}
94 dispatch_sync(globalQueue, ^{
Jordan Rose56138262013-05-24 21:43:11 +000095 // expected-note@-1 {{Calling anonymous block}}
96 // expected-note@-2 {{Returning to caller}}
Jordan Rose2d98b972012-11-15 02:07:23 +000097 x = 0;
98 // expected-note@-1 {{The value 0 is assigned to 'x'}}
Jordan Rose2d98b972012-11-15 02:07:23 +000099 });
100
101 return 1 / x; // expected-warning{{Division by zero}}
102 // expected-note@-1 {{Division by zero}}
103}
104
Jordan Rose9a339132012-12-07 19:56:29 +0000105int testDispatchSyncInliningNoPruning(int coin) {
106 // This tests exactly the same case as above, except on a bug report where
107 // path pruning is disabled (an uninitialized variable capture).
108 // In this case
109 extern dispatch_queue_t globalQueue;
110
111 __block int y;
112
113 // expected-note@+1 {{Calling 'dispatch_sync'}}
114 dispatch_sync(globalQueue, ^{
Jordan Rose56138262013-05-24 21:43:11 +0000115 // expected-note@-1 {{Calling anonymous block}}
Jordan Rose9a339132012-12-07 19:56:29 +0000116 int x;
Ted Kremenek37c777e2013-02-26 19:44:38 +0000117 // expected-note@-1 {{'x' declared without an initial value}}
Jordan Rose9a339132012-12-07 19:56:29 +0000118 ^{ y = x; }(); // expected-warning{{Variable 'x' is uninitialized when captured by block}}
Ted Kremenek37c777e2013-02-26 19:44:38 +0000119 // expected-note@-1 {{'x' is uninitialized when captured by block}}
Jordan Rose9a339132012-12-07 19:56:29 +0000120 });
121
122 return y;
123}
124
Jordan Rose2d98b972012-11-15 02:07:23 +0000125
Jordan Rosecea47b72013-05-03 05:47:24 +0000126@interface PointerWrapper
127- (int *)getPtr;
128@end
129
130id getNil() {
131 return 0;
132}
133
134void testNilReceiverHelper(int *x) {
135 *x = 1; // expected-warning {{Dereference of null pointer}}
136 // expected-note@-1 {{Dereference of null pointer (loaded from variable 'x')}}
137}
138
Artem Dergachevfee10102017-12-20 01:03:22 +0000139void testNilReceiver(id *x, id *y, id *z) {
140 // FIXME: Should say "Assuming pointer value is null" instead.
141 // For some reason we're displaying different notes for
142 // tracked and untracked pointers.
143 if (*y) {} // expected-note {{Assuming the condition is false}}
144 // expected-note@-1 {{Taking false branch}}
145 if (*x) { // expected-note {{Assuming pointer value is null}}
Jordan Rosecea47b72013-05-03 05:47:24 +0000146 // expected-note@-1 {{Taking false branch}}
147 return;
148 }
Artem Dergachevfee10102017-12-20 01:03:22 +0000149 // FIXME: Should say "Assuming pointer value is null" instead.
150 if (*z) {} // expected-note {{Assuming the condition is false}}
151 // expected-note@-1 {{Taking false branch}}
Jordan Rosecea47b72013-05-03 05:47:24 +0000152 testNilReceiverHelper([*x getPtr]);
153 // expected-note@-1 {{'getPtr' not called because the receiver is nil}}
154 // expected-note@-2 {{Passing null pointer value via 1st parameter 'x'}}
155 // expected-note@-3 {{Calling 'testNilReceiverHelper'}}
156}
157
Anna Zaks6afa8f12013-05-13 23:49:51 +0000158id testCreateArrayLiteral(id myNil) {
159 if (myNil) // expected-note {{Assuming 'myNil' is nil}}
160 ; // expected-note@-1 {{Taking false branch}}
161 return @[ @"a", myNil, @"c" ]; // expected-warning {{Array element cannot be nil}}
162 //expected-note@-1 {{Array element cannot be nil}}
163}
Jordan Rosecea47b72013-05-03 05:47:24 +0000164
Jordan Rose5fbe7f92013-08-01 22:16:30 +0000165// <rdar://problem/14611722>
166id testAutoreleaseTakesEffectInDispatch() {
167 static dispatch_once_t token = 0;
168 dispatch_once(&token, ^{});
169
170 id x = [[[[NSObject alloc] init] autorelease] autorelease];
Anna Zaks232ecfd2016-12-15 22:55:03 +0000171 // expected-note@-1 {{Method returns an instance of NSObject with a +1 retain count}}
Jordan Rose7699e4a2013-08-01 22:16:36 +0000172 // expected-note@-2 {{Object autoreleased}}
173 // expected-note@-3 {{Object autoreleased}}
Jordan Rose5fbe7f92013-08-01 22:16:30 +0000174
Jordan Rose7699e4a2013-08-01 22:16:36 +0000175 dispatch_once(&token, ^{}); // don't crash, don't warn here
Jordan Rose5fbe7f92013-08-01 22:16:30 +0000176
Jordan Rose7699e4a2013-08-01 22:16:36 +0000177 return x; // expected-warning{{Object autoreleased too many times}}
178 // expected-note@-1 {{Object was autoreleased 2 times but the object has a +0 retain count}}
Jordan Rose5fbe7f92013-08-01 22:16:30 +0000179}
180
181void testNullDereferenceInDispatch() {
182 dispatch_once(0, ^{}); // no-warning, don't crash
183}
184