Ted Kremenek | a43df95 | 2012-09-21 00:09:11 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,unix.API,osx.API %s -analyzer-store=region -analyzer-output=plist -analyzer-ipa=inlining -analyzer-eagerly-assume -analyzer-config faux-bodies=true -fblocks -verify -o %t.plist |
| 2 | // RUN: FileCheck --input-file=%t.plist %s |
Ted Kremenek | 99d9838 | 2010-04-08 19:53:31 +0000 | [diff] [blame] | 3 | |
| 4 | struct _opaque_pthread_once_t { |
| 5 | long __sig; |
| 6 | char __opaque[8]; |
| 7 | }; |
| 8 | typedef struct _opaque_pthread_once_t __darwin_pthread_once_t; |
| 9 | typedef __darwin_pthread_once_t pthread_once_t; |
| 10 | int pthread_once(pthread_once_t *, void (*)(void)); |
Ted Kremenek | b12fbc2 | 2010-11-16 18:47:04 +0000 | [diff] [blame] | 11 | typedef long unsigned int __darwin_size_t; |
| 12 | typedef __darwin_size_t size_t; |
Ted Kremenek | c1275da | 2012-01-03 23:43:13 +0000 | [diff] [blame] | 13 | void *calloc(size_t, size_t); |
Ted Kremenek | b12fbc2 | 2010-11-16 18:47:04 +0000 | [diff] [blame] | 14 | void *malloc(size_t); |
Ted Kremenek | c1275da | 2012-01-03 23:43:13 +0000 | [diff] [blame] | 15 | void *realloc(void *, size_t); |
Jordan Rose | eafaad2 | 2012-10-30 01:37:16 +0000 | [diff] [blame] | 16 | void *reallocf(void *, size_t); |
Ted Kremenek | 3e97758 | 2012-01-11 08:13:21 +0000 | [diff] [blame] | 17 | void *alloca(size_t); |
| 18 | void *valloc(size_t); |
Ted Kremenek | 99d9838 | 2010-04-08 19:53:31 +0000 | [diff] [blame] | 19 | |
Ted Kremenek | a43df95 | 2012-09-21 00:09:11 +0000 | [diff] [blame] | 20 | typedef union { |
| 21 | struct _os_object_s *_os_obj; |
| 22 | struct dispatch_object_s *_do; |
| 23 | struct dispatch_continuation_s *_dc; |
| 24 | struct dispatch_queue_s *_dq; |
| 25 | struct dispatch_queue_attr_s *_dqa; |
| 26 | struct dispatch_group_s *_dg; |
| 27 | struct dispatch_source_s *_ds; |
| 28 | struct dispatch_source_attr_s *_dsa; |
| 29 | struct dispatch_semaphore_s *_dsema; |
| 30 | struct dispatch_data_s *_ddata; |
| 31 | struct dispatch_io_s *_dchannel; |
| 32 | struct dispatch_operation_s *_doperation; |
| 33 | struct dispatch_disk_s *_ddisk; |
| 34 | } dispatch_object_t __attribute__((__transparent_union__)); |
| 35 | |
Ted Kremenek | 99d9838 | 2010-04-08 19:53:31 +0000 | [diff] [blame] | 36 | typedef void (^dispatch_block_t)(void); |
| 37 | typedef long dispatch_once_t; |
Ted Kremenek | a43df95 | 2012-09-21 00:09:11 +0000 | [diff] [blame] | 38 | typedef struct dispatch_queue_s *dispatch_queue_t; |
Ted Kremenek | 99d9838 | 2010-04-08 19:53:31 +0000 | [diff] [blame] | 39 | void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block); |
Ted Kremenek | a43df95 | 2012-09-21 00:09:11 +0000 | [diff] [blame] | 40 | void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); |
Ted Kremenek | 381d1bf | 2010-02-25 00:20:35 +0000 | [diff] [blame] | 41 | |
Ted Kremenek | fc89323 | 2010-02-25 01:16:07 +0000 | [diff] [blame] | 42 | #ifndef O_CREAT |
| 43 | #define O_CREAT 0x0200 |
| 44 | #define O_RDONLY 0x0000 |
| 45 | #endif |
| 46 | int open(const char *, int, ...); |
Ted Kremenek | 99d9838 | 2010-04-08 19:53:31 +0000 | [diff] [blame] | 47 | int close(int fildes); |
Ted Kremenek | 381d1bf | 2010-02-25 00:20:35 +0000 | [diff] [blame] | 48 | |
| 49 | void test_open(const char *path) { |
| 50 | int fd; |
| 51 | fd = open(path, O_RDONLY); // no-warning |
| 52 | if (!fd) |
| 53 | close(fd); |
| 54 | |
| 55 | fd = open(path, O_CREAT); // expected-warning{{Call to 'open' requires a third argument when the 'O_CREAT' flag is set}} |
| 56 | if (!fd) |
| 57 | close(fd); |
| 58 | } |
Ted Kremenek | 99d9838 | 2010-04-08 19:53:31 +0000 | [diff] [blame] | 59 | |
| 60 | void test_dispatch_once() { |
| 61 | dispatch_once_t pred = 0; |
| 62 | do { if (__builtin_expect(*(&pred), ~0l) != ~0l) dispatch_once((&pred), (^() {})); } while (0); // expected-warning{{Call to 'dispatch_once' uses the local variable 'pred' for the predicate value}} |
| 63 | } |
| 64 | void test_dispatch_once_neg() { |
| 65 | static dispatch_once_t pred = 0; |
| 66 | do { if (__builtin_expect(*(&pred), ~0l) != ~0l) dispatch_once((&pred), (^() {})); } while (0); // no-warning |
| 67 | } |
| 68 | |
| 69 | void test_pthread_once_aux(); |
| 70 | |
| 71 | void test_pthread_once() { |
| 72 | pthread_once_t pred = {0x30B1BCBA, {0}}; |
| 73 | pthread_once(&pred, test_pthread_once_aux); // expected-warning{{Call to 'pthread_once' uses the local variable 'pred' for the "control" value}} |
| 74 | } |
| 75 | void test_pthread_once_neg() { |
| 76 | static pthread_once_t pred = {0x30B1BCBA, {0}}; |
| 77 | pthread_once(&pred, test_pthread_once_aux); // no-warning |
| 78 | } |
Ted Kremenek | b12fbc2 | 2010-11-16 18:47:04 +0000 | [diff] [blame] | 79 | |
| 80 | // PR 2899 - warn of zero-sized allocations to malloc(). |
| 81 | void pr2899() { |
| 82 | char* foo = malloc(0); // expected-warning{{Call to 'malloc' has an allocation size of 0 bytes}} |
| 83 | for (unsigned i = 0; i < 100; i++) { |
| 84 | foo[i] = 0; |
| 85 | } |
| 86 | } |
| 87 | void pr2899_nowarn(size_t size) { |
| 88 | char* foo = malloc(size); // no-warning |
| 89 | for (unsigned i = 0; i < 100; i++) { |
| 90 | foo[i] = 0; |
| 91 | } |
| 92 | } |
Ted Kremenek | c1275da | 2012-01-03 23:43:13 +0000 | [diff] [blame] | 93 | void test_calloc(void) { |
| 94 | char *foo = calloc(0, 42); // expected-warning{{Call to 'calloc' has an allocation size of 0 bytes}} |
| 95 | for (unsigned i = 0; i < 100; i++) { |
| 96 | foo[i] = 0; |
| 97 | } |
| 98 | } |
| 99 | void test_calloc2(void) { |
| 100 | char *foo = calloc(42, 0); // expected-warning{{Call to 'calloc' has an allocation size of 0 bytes}} |
| 101 | for (unsigned i = 0; i < 100; i++) { |
| 102 | foo[i] = 0; |
| 103 | } |
| 104 | } |
| 105 | void test_calloc_nowarn(size_t nmemb, size_t size) { |
| 106 | char *foo = calloc(nmemb, size); // no-warning |
| 107 | for (unsigned i = 0; i < 100; i++) { |
| 108 | foo[i] = 0; |
| 109 | } |
| 110 | } |
| 111 | void test_realloc(char *ptr) { |
| 112 | char *foo = realloc(ptr, 0); // expected-warning{{Call to 'realloc' has an allocation size of 0 bytes}} |
| 113 | for (unsigned i = 0; i < 100; i++) { |
| 114 | foo[i] = 0; |
| 115 | } |
| 116 | } |
Jordan Rose | eafaad2 | 2012-10-30 01:37:16 +0000 | [diff] [blame] | 117 | void test_reallocf(char *ptr) { |
| 118 | char *foo = reallocf(ptr, 0); // expected-warning{{Call to 'reallocf' has an allocation size of 0 bytes}} |
| 119 | for (unsigned i = 0; i < 100; i++) { |
| 120 | foo[i] = 0; |
| 121 | } |
| 122 | } |
Ted Kremenek | c1275da | 2012-01-03 23:43:13 +0000 | [diff] [blame] | 123 | void test_realloc_nowarn(char *ptr, size_t size) { |
| 124 | char *foo = realloc(ptr, size); // no-warning |
| 125 | for (unsigned i = 0; i < 100; i++) { |
| 126 | foo[i] = 0; |
| 127 | } |
| 128 | } |
Jordan Rose | eafaad2 | 2012-10-30 01:37:16 +0000 | [diff] [blame] | 129 | void test_reallocf_nowarn(char *ptr, size_t size) { |
| 130 | char *foo = reallocf(ptr, size); // no-warning |
| 131 | for (unsigned i = 0; i < 100; i++) { |
| 132 | foo[i] = 0; |
| 133 | } |
| 134 | } |
Ted Kremenek | 3e97758 | 2012-01-11 08:13:21 +0000 | [diff] [blame] | 135 | void test_alloca() { |
| 136 | char *foo = alloca(0); // expected-warning{{Call to 'alloca' has an allocation size of 0 bytes}} |
| 137 | for(unsigned i = 0; i < 100; i++) { |
| 138 | foo[i] = 0; |
| 139 | } |
| 140 | } |
| 141 | void test_alloca_nowarn(size_t sz) { |
| 142 | char *foo = alloca(sz); // no-warning |
| 143 | for(unsigned i = 0; i < 100; i++) { |
| 144 | foo[i] = 0; |
| 145 | } |
| 146 | } |
| 147 | void test_builtin_alloca() { |
| 148 | char *foo2 = __builtin_alloca(0); // expected-warning{{Call to 'alloca' has an allocation size of 0 bytes}} |
| 149 | for(unsigned i = 0; i < 100; i++) { |
| 150 | foo2[i] = 0; |
| 151 | } |
| 152 | } |
| 153 | void test_builtin_alloca_nowarn(size_t sz) { |
| 154 | char *foo2 = __builtin_alloca(sz); // no-warning |
| 155 | for(unsigned i = 0; i < 100; i++) { |
| 156 | foo2[i] = 0; |
| 157 | } |
| 158 | } |
| 159 | void test_valloc() { |
| 160 | char *foo = valloc(0); // expected-warning{{Call to 'valloc' has an allocation size of 0 bytes}} |
| 161 | for(unsigned i = 0; i < 100; i++) { |
| 162 | foo[i] = 0; |
| 163 | } |
| 164 | } |
| 165 | void test_valloc_nowarn(size_t sz) { |
| 166 | char *foo = valloc(sz); // no-warning |
| 167 | for(unsigned i = 0; i < 100; i++) { |
| 168 | foo[i] = 0; |
| 169 | } |
| 170 | } |
Ted Kremenek | be87972 | 2012-09-13 18:18:37 +0000 | [diff] [blame] | 171 | |
| 172 | // Test dispatch_once being a macro that wraps a call to _dispatch_once, which in turn |
| 173 | // calls the real dispatch_once. |
| 174 | |
| 175 | static inline void _dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) |
| 176 | { |
| 177 | dispatch_once(predicate, block); |
| 178 | } |
| 179 | |
| 180 | #define dispatch_once _dispatch_once |
| 181 | |
| 182 | void test_dispatch_once_in_macro() { |
| 183 | dispatch_once_t pred = 0; |
| 184 | dispatch_once(&pred, ^(){}); // expected-warning {{Call to 'dispatch_once' uses the local variable 'pred' for the predicate value}} |
| 185 | } |
Ted Kremenek | a43df95 | 2012-09-21 00:09:11 +0000 | [diff] [blame] | 186 | |
| 187 | // Test inlining of dispatch_sync. |
| 188 | void test_dispatch_sync(dispatch_queue_t queue, int *q) { |
| 189 | int *p = 0; |
| 190 | dispatch_sync(queue, ^(void){ |
| 191 | if (q) { |
| 192 | *p = 1; // expected-warning {{null pointer}} |
| 193 | } |
| 194 | }); |
| 195 | } |
| 196 | |
Ted Kremenek | cc85d21 | 2012-09-21 00:52:24 +0000 | [diff] [blame] | 197 | // Test inlining if dispatch_once. |
| 198 | void test_inline_dispatch_once() { |
| 199 | static dispatch_once_t pred; |
| 200 | int *p = 0; |
| 201 | dispatch_once(&pred, ^(void) { |
| 202 | *p = 1; // expected-warning {{null}} |
| 203 | }); |
| 204 | } |
| 205 | |