xref: /llvm-project/clang/test/Analysis/edges-new.mm (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
1// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,deadcode.DeadStores,osx.cocoa.RetainCount,unix.Malloc,unix.MismatchedDeallocator -analyzer-output=plist -analyzer-config deadcode.DeadStores:ShowFixIts=true -o %t -w %s
2// RUN: %normalize_plist <%t | diff -ub %S/Inputs/expected-plists/edges-new.mm.plist -
3
4//===----------------------------------------------------------------------===//
5// Forward declarations (from headers).
6//===----------------------------------------------------------------------===//
7
8typedef const struct __CFNumber * CFNumberRef;
9typedef const struct __CFAllocator * CFAllocatorRef;
10extern const CFAllocatorRef kCFAllocatorDefault;
11typedef signed long CFIndex;
12enum {
13  kCFNumberSInt8Type = 1,
14  kCFNumberSInt16Type = 2,
15  kCFNumberSInt32Type = 3,
16  kCFNumberSInt64Type = 4,
17  kCFNumberFloat32Type = 5,
18  kCFNumberFloat64Type = 6,
19  kCFNumberCharType = 7,
20  kCFNumberShortType = 8,
21  kCFNumberIntType = 9,
22  kCFNumberLongType = 10,
23  kCFNumberLongLongType = 11,
24  kCFNumberFloatType = 12,
25  kCFNumberDoubleType = 13,
26  kCFNumberCFIndexType = 14,
27  kCFNumberNSIntegerType = 15,
28  kCFNumberCGFloatType = 16,
29  kCFNumberMaxType = 16
30};
31typedef CFIndex CFNumberType;
32CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr);
33
34#define nil ((id)0)
35
36__attribute__((objc_root_class))
37@interface NSObject
38+ (instancetype) alloc;
39- (instancetype) init;
40- (instancetype)retain;
41- (void)release;
42@end
43
44@interface NSArray : NSObject
45@end
46
47//===----------------------------------------------------------------------===//
48// Basic tracking of null and tests for null.
49//===----------------------------------------------------------------------===//
50
51void test_null_init(void) {
52  int *p = 0;
53  *p = 0xDEADBEEF;
54}
55
56void test_null_assign(void) {
57  int *p;
58  p = 0;
59  *p = 0xDEADBEEF;
60}
61
62void test_null_assign_transitive(void) {
63  int *p;
64  p = 0;
65  int *q = p;
66  *q = 0xDEADBEEF;
67}
68
69void test_null_cond(int *p) {
70  if (!p) {
71    *p = 0xDEADBEEF;
72  }
73}
74
75void test_null_cond_transitive(int *q) {
76  if (!q) {
77    int *p = q;
78    *p = 0xDEADBEEF;
79  }
80}
81
82void test_null_field(void) {
83  struct s { int *p; } x;
84  x.p = 0;
85  *(x.p) = 0xDEADBEEF;
86}
87
88void test_assumptions(int a, int b)
89{
90  if (a == 0) {
91    return;
92  }
93  if (b != 0) {
94    return;
95  }
96  int *p = 0;
97  *p = 0xDEADBEEF;
98}
99
100int *bar_cond_assign();
101int test_cond_assign() {
102  int *p;
103  if ((p = bar_cond_assign()))
104    return 1;
105  return *p;
106}
107
108//===----------------------------------------------------------------------===//
109// Diagnostics for leaks and "noreturn" paths.
110//===----------------------------------------------------------------------===//
111
112
113// leak reports should not show paths that end with exit() (but ones that don't end with exit())
114
115void stop() __attribute__((noreturn));
116
117void rdar8331641(int x) {
118  signed z = 1;
119  CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &z); // expected-warning{{leak}}
120  if (x)
121    stop();
122  (void) value;
123}
124
125//===----------------------------------------------------------------------===//
126// Test loops and control-flow.
127//===----------------------------------------------------------------------===//
128
129void test_objc_fast_enumeration(NSArray *x) {
130  id obj;
131  for (obj in x)
132    *(volatile int *)0 = 0;
133}
134
135void test_objc_fast_enumeration_2(id arr) {
136  int x;
137  for (id obj in arr) {
138    x = 1;
139  }
140  x += 1;
141}
142
143// Test that loops are documented in the path.
144void rdar12280665() {
145  for (unsigned i = 0; i < 2; ++i) {
146	  if (i == 1) {
147		  int *p = 0;
148		  *p = 0xDEADBEEF; // expected-warning {{dereference}}
149	  }
150  }
151}
152
153// Test for a "loop executed 0 times" diagnostic.
154int *radar12322528_bar();
155
156void radar12322528_for(int x) {
157  int z;
158  int *p = 0;
159  for (unsigned i = 0; i < x; ++i) {
160    p = radar12322528_bar();
161  }
162  *p = 0xDEADBEEF;
163}
164
165void radar12322528_while(int x) {
166  int *p = 0;
167  unsigned i = 0;
168  for ( ; i < x ; ) {
169    ++i;
170    p = radar12322528_bar();
171  }
172  *p = 0xDEADBEEF;
173}
174
175void radar12322528_foo_2() {
176  int *p = 0;
177  for (unsigned i = 0; i < 2; ++i) {
178    if (i == 0)
179      continue;
180
181    if (i == 1) {
182
183      break;
184    }
185  }
186  *p = 0xDEADBEEF;
187}
188
189void test_loop_diagnostics() {
190  int *p = 0;
191  for (int i = 0; i < 2; ++i) { p = 0; }
192  *p = 1;
193}
194
195void test_loop_diagnostics_2() {
196  int *p = 0;
197
198  for (int i = 0; i < 2; ) {
199
200    ++i;
201
202    p = 0;
203
204  }
205
206  *p = 1;
207}
208
209void test_loop_diagnostics_3() {
210  int z;
211  int y;
212  int k;
213  int *p = 0;
214  int i = 0;
215  while (i < 2) {
216    ++i;
217    p = 0;
218  }
219  * p = 1;
220}
221
222void test_do_while() {
223  unsigned i = 0;
224
225  int *p;
226
227  do {
228
229    ++i;
230    p = 0;
231
232  } while (i< 2);
233
234  *p = 0xDEADBEEF;
235}
236
237
238void test_logical_and() {
239  int *p = 0;
240  if (1 && 2) {
241    *p = 0xDEADBEEF;
242  }
243}
244
245void test_logical_or() {
246  int *p = 0;
247  if (0 || 2) {
248    *p = 0xDEADBEEF;
249  }
250}
251
252void test_logical_or_call() {
253  extern int call(int);
254  int *p = 0;
255  if (call(0 || 2)) {
256    *p = 0xDEADBEEF;
257  }
258}
259
260void test_nested_logicals(int coin) {
261  int *p = 0;
262
263  if ((0 || 0) || coin) {
264    *p = 0xDEADBEEF;
265  }
266
267  if (0 || (0 || !coin)) {
268    *p = 0xDEADBEEF;
269  }
270}
271
272void test_deeply_nested_logicals() {
273  extern int call(int);
274  int *p = 0;
275
276  if ((0 || (5 && 0)) ? 0 : ((0 || 4) ? call(1 && 5) : 0)) {
277
278    *p = 0xDEADBEEF;
279  }
280}
281
282void test_ternary(int x, int *y) {
283  int z = x ? 0 : 1;
284
285  int *p = z ? y : 0;
286
287  *p = 0xDEADBEEF;
288}
289
290void testUseless(int *y) {
291  if (y) {
292
293  }
294  if (y) {
295
296  }
297  int *p = 0;
298  *p = 0xDEADBEEF;
299}
300
301//===----------------------------------------------------------------------===//
302// Interprocedural tests.
303//===----------------------------------------------------------------------===//
304
305@interface IPA_Foo
306- (int *) returnsPointer;
307@end
308
309int testFoo(IPA_Foo *x) {
310  if (x)
311    return 1;
312  return *[x returnsPointer];
313}
314
315@interface IPA_X : NSObject
316- (int *)getPointer;
317@end
318
319void test1_IPA_X() {
320  IPA_X *x = nil;
321  *[x getPointer] = 1; // here
322}
323
324
325@interface IPA_Y : NSObject
326- (IPA_Y *)opaque;
327- (IPA_X *)getX;
328@end
329
330@implementation IPA_Y
331- (IPA_X *)getX {
332  return nil;
333}
334@end
335
336void test_IPA_Y(IPA_Y *y) {
337  if (y)
338    return;
339
340  IPA_X *x = [[y opaque] getX]; // here
341  *[x getPointer] = 1;
342}
343
344// From diagnostics/report-issues-within-main-file.cpp:
345void causeDivByZeroInMain(int in) {
346  int m = 0;
347  m = in/m;
348  m++;
349}
350
351void mainPlusMain() {
352  int i = 0;
353  i++;
354  causeDivByZeroInMain(i);
355  i++;
356}
357
358// From inlining/path-notes.c:
359int *getZero() {
360  int *p = 0;
361  return p;
362}
363
364void usePointer(int *p) {
365  *p = 1;
366}
367
368void testUseOfNullPointer() {
369  // Test the case where an argument expression is itself a call.
370  usePointer(getZero());
371}
372
373
374//===----------------------------------------------------------------------===//
375// Misc. tests.
376//===----------------------------------------------------------------------===//
377
378// Test for tracking null state of ivars.
379@interface RDar12114812 : NSObject  { char *p; }
380@end
381@implementation RDar12114812
382- (void)test {
383  p = 0;
384  *p = 1;
385}
386@end
387
388// Test diagnostics for initialization of structs.
389void RDar13295437_f(void *i) __attribute__((__nonnull__));
390struct RDar13295437_S { int *i; };
391int  RDar13295437() {
392  struct RDar13295437_S s = {0};
393  struct RDar13295437_S *sp = &s;
394  RDar13295437_f(sp->i);
395  return 0;
396}
397
398
399void testCast(int coin) {
400  if (coin) {
401    (void)(1+2);
402    (void)(2+3);
403    (void)(3+4);
404    *(volatile int *)0 = 1;
405  }
406}
407
408// The following previously crashed when generating extensive diagnostics.
409@interface RDar10797980_help
410@property (readonly) int x;
411@end
412@interface RDar10797980 : NSObject {
413  RDar10797980_help *y;
414}
415- (void) test;
416@end
417@implementation RDar10797980
418- (void) test {
419  if (y.x == 1) {
420    int *p = 0;
421    *p = 0xDEADBEEF; // expected-warning {{deference}}
422  }
423}
424
425// The original source for the above Radar contains another problem:
426// if the end-of-path node is an implicit statement, it may not have a valid
427// source location.
428- (void)test2 {
429  if (bar_cond_assign()) {
430    id foo = [[RDar10797980 alloc] init]; // leak
431  }
432  (void)y; // first statement after the 'if' is an implicit 'self' DeclRefExpr
433}
434
435@end
436
437void variousLoops(id input) {
438  extern int a();
439  extern int b();
440  extern int c();
441
442  extern int work();
443
444  while (a()) {
445    work();
446    work();
447    work();
448    *(volatile int *)0 = 1;
449  }
450
451  int first = 1;
452  do {
453    work();
454    work();
455    work();
456    if (!first)
457      *(volatile int *)0 = 1;
458    first = 0;
459  } while (a());
460
461  for (int i = 0; i != b(); ++i) {
462    work();
463    *(volatile int *)0 = 1;
464  }
465
466  for (id x in input) {
467    work();
468    work();
469    work();
470    (void)x;
471    *(volatile int *)0 = 1;
472  }
473
474  int z[] = {1,2};
475  for (int y : z) {
476    work();
477    work();
478    work();
479    (void)y;
480  }
481
482  int empty[] = {};
483  for (int y : empty) {
484    work();
485    work();
486    work();
487    (void)y;
488  }
489
490  for (int i = 0; ; ++i) {
491    work();
492    if (i == b())
493      break;
494  }
495
496  int i;
497  for (i = 0; i != b(); ++i) {
498    work();
499    *(volatile int *)0 = 1;
500  }
501
502  for (; i != b(); ++i) {
503    work();
504    *(volatile int *)0 = 1;
505  }
506
507  for (; i != b(); ) {
508    work();
509    if (i == b())
510      break;
511    *(volatile int *)0 = 1;
512  }
513
514  for (;;) {
515    work();
516    if (i == b())
517      break;
518  }
519
520  *(volatile int *)0 = 1;
521}
522
523void *malloc(unsigned long);
524void *realloc(void *, unsigned long);
525void free(void *);
526
527void reallocDiagnostics() {
528  char * buf = (char*)malloc(100);
529  char * tmp;
530  tmp = (char*)realloc(buf, 0x1000000);
531  if (!tmp) {
532    return;// expected-warning {{leak}}
533  }
534  buf = tmp;
535  free(buf);
536}
537
538template <typename T>
539class unique_ptr {
540  T *ptr;
541public:
542  explicit unique_ptr(T *p) : ptr(p) {}
543  ~unique_ptr() { delete ptr; }
544};
545
546void test() {
547  int i = 0;
548  ++i;
549
550  unique_ptr<int> p(new int[4]);
551  {
552    ++i;
553  }
554}
555
556void longLines() {
557  id foo = [[NSObject alloc] init]; // leak
558  id bar =
559           [foo retain];
560  [bar release];
561  id baz = [foo
562              retain];
563  [baz release];
564  // This next line is intentionally longer than 80 characters.
565  id garply = [foo                                                              retain];
566  [garply release];
567}
568
569#define POINTER(T) T*
570POINTER(void) testMacroInFunctionDecl(void *q) {
571  int *p = 0;
572  *p = 1;
573  return q;
574}
575
576namespace rdar14960554 {
577  class Foo {
578    int a = 1;
579    int b = 2;
580    int c = 3;
581
582    Foo() :
583      a(0),
584      c(3) {
585      // Check that we don't have an edge to the in-class initializer for 'b'.
586      if (b == 2)
587        *(volatile int *)0 = 1;
588    }
589  };
590}
591
592