misc-ps.m revision f7a0cf426eddae76e1a71dd2295631a2cf0560af
1// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=basic --verify -fblocks %s &&
2// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s &&
3// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s &&
4// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s
5
6typedef struct objc_selector *SEL;
7typedef signed char BOOL;
8typedef int NSInteger;
9typedef unsigned int NSUInteger;
10typedef struct _NSZone NSZone;
11@class NSInvocation, NSArray, NSMethodSignature, NSCoder, NSString, NSEnumerator;
12@protocol NSObject  - (BOOL)isEqual:(id)object; @end
13@protocol NSCopying  - (id)copyWithZone:(NSZone *)zone; @end
14@protocol NSMutableCopying  - (id)mutableCopyWithZone:(NSZone *)zone; @end
15@protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder; @end
16@interface NSObject <NSObject> {} - (id)init; @end
17extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
18@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>
19- (NSUInteger)length;
20+ (id)stringWithUTF8String:(const char *)nullTerminatedCString;
21@end extern NSString * const NSBundleDidLoadNotification;
22@interface NSAssertionHandler : NSObject {}
23+ (NSAssertionHandler *)currentHandler;
24- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...;
25@end
26extern NSString * const NSConnectionReplyMode;
27typedef float CGFloat;
28typedef struct _NSPoint {
29    CGFloat x;
30    CGFloat y;
31} NSPoint;
32typedef struct _NSSize {
33    CGFloat width;
34    CGFloat height;
35} NSSize;
36typedef struct _NSRect {
37    NSPoint origin;
38    NSSize size;
39} NSRect;
40
41// Reduced test case from crash in <rdar://problem/6253157>
42@interface A @end
43@implementation A
44- (void)foo:(void (^)(NSObject *x))block {
45  if (!((block != ((void *)0)))) {}
46}
47@end
48
49// Reduced test case from crash in PR 2796;
50//  http://llvm.org/bugs/show_bug.cgi?id=2796
51
52unsigned foo(unsigned x) { return __alignof__((x)) + sizeof(x); }
53
54// Improvement to path-sensitivity involving compound assignments.
55//  Addresses false positive in <rdar://problem/6268365>
56//
57
58unsigned r6268365Aux();
59
60void r6268365() {
61  unsigned x = 0;
62  x &= r6268365Aux();
63  unsigned j = 0;
64    
65  if (x == 0) ++j;
66  if (x == 0) x = x / j; // no-warning
67}
68
69void divzeroassume(unsigned x, unsigned j) {  
70  x /= j;  
71  if (j == 0) x /= 0;     // no-warning
72  if (j == 0) x /= j;     // no-warning
73  if (j == 0) x = x / 0;  // no-warning
74}
75
76void divzeroassumeB(unsigned x, unsigned j) {  
77  x = x / j;  
78  if (j == 0) x /= 0;     // no-warning
79  if (j == 0) x /= j;     // no-warning
80  if (j == 0) x = x / 0;  // no-warning
81}
82
83// InitListExpr processing
84
85typedef float __m128 __attribute__((__vector_size__(16), __may_alias__));
86__m128 return128() {
87  // This compound literal has a Vector type.  We currently just
88  // return UnknownVal.
89  return __extension__(__m128) { 0.0f, 0.0f, 0.0f, 0.0f };
90}
91
92typedef long long __v2di __attribute__ ((__vector_size__ (16)));
93typedef long long __m128i __attribute__ ((__vector_size__ (16), __may_alias__));
94__m128i vec128i(long long __q1, long long __q0) {
95  // This compound literal returns true for both isVectorType() and 
96  // isIntegerType().
97  return __extension__ (__m128i)(__v2di){ __q0, __q1 };
98}
99
100// Zero-sized VLAs.
101void check_zero_sized_VLA(int x) {
102  if (x)
103    return;
104
105  int vla[x]; // expected-warning{{Variable-length array 'vla' has zero elements (undefined behavior)}}
106}
107
108void check_uninit_sized_VLA() {
109  int x;
110  int vla[x]; // expected-warning{{Variable-length array 'vla' garbage value for array size}}
111}
112
113// sizeof(void)
114// - Tests a regression reported in PR 3211: http://llvm.org/bugs/show_bug.cgi?id=3211
115void handle_sizeof_void(unsigned flag) {
116  int* p = 0;
117
118  if (flag) {
119    if (sizeof(void) == 1)
120      return;
121    // Infeasible.
122    *p = 1; // no-warning
123  }
124  
125  void* q;
126  
127  if (!flag) {
128    if (sizeof(*q) == 1)
129      return;
130    // Infeasibe.
131    *p = 1; // no-warning
132  }
133    
134  // Infeasible.
135  *p = 1; // no-warning
136}
137
138// PR 3422
139void pr3422_helper(char *p);
140void pr3422() {
141  char buf[100];
142  char *q = &buf[10];
143  pr3422_helper(&q[1]);
144}
145
146// PR 3543 (handle empty statement expressions)
147void pr_3543(void) {
148  ({});
149}
150
151// <rdar://problem/6611677>
152// This test case test the use of a vector type within an array subscript
153// expression.
154typedef long long __a64vector __attribute__((__vector_size__(8)));
155typedef long long __a128vector __attribute__((__vector_size__(16)));
156static inline __a64vector __attribute__((__always_inline__, __nodebug__))  
157my_test_mm_movepi64_pi64(__a128vector a) {
158  return (__a64vector)a[0];
159}
160
161// Test basic tracking of ivars associated with 'self'.
162@interface SelfIvarTest : NSObject {
163  int flag;
164}
165- (void)test_self_tracking;
166@end
167
168@implementation SelfIvarTest
169- (void)test_self_tracking {
170  char *p = 0;
171  char c;
172
173  if (flag)
174    p = "hello";
175
176  if (flag)
177    c = *p; // no-warning
178}
179@end
180
181// PR 3770
182char pr3770(int x) {
183  int y = x & 0x2;
184  char *p = 0;
185  if (y == 1)
186    p = "hello";
187
188  if (y == 1)
189    return p[0]; // no-warning
190    
191  return 'a';
192}
193
194// PR 3772
195// - We just want to test that this doesn't crash the analyzer.
196typedef struct st ST;
197struct st { char *name; };
198extern ST *Cur_Pu;
199
200void pr3772(void)
201{
202  static ST *last_Cur_Pu;
203  if (last_Cur_Pu == Cur_Pu) {
204    return;
205  } 
206}
207
208// PR 3780 - This tests that StmtIterator isn't broken for VLAs in DeclGroups.
209void pr3780(int sz) { typedef double MAT[sz][sz]; }
210
211// <rdar://problem/6695527> - Test that we don't symbolicate doubles before
212// we are ready to do something with them.
213int rdar6695527(double x) {
214  if (!x) { return 0; }
215  return 1;
216}
217
218// <rdar://problem/6708148> - Test that we properly invalidate structs
219//  passed-by-reference to a function.
220void pr6708148_invalidate(NSRect *x);
221void pr6708148_use(NSRect x);
222void pr6708148_test(void) {
223  NSRect x;
224  pr6708148_invalidate(&x);
225  pr6708148_use(x); // no-warning
226}
227
228// Handle both kinds of noreturn attributes for pruning paths.
229void rdar_6777003_noret() __attribute__((noreturn));
230void rdar_6777003_analyzer_noret() __attribute__((analyzer_noreturn));
231
232void rdar_6777003(int x) {
233  int *p = 0;
234  
235  if (x == 1) {
236    rdar_6777003_noret();
237    *p = 1; // no-warning;    
238  }
239  
240  if (x == 2) {
241    rdar_6777003_analyzer_noret();
242    *p = 1; // no-warning;
243  }
244  
245  *p = 1; // expected-warning{{Dereference of null pointer}}  
246}
247
248// For pointer arithmetic, --/++ should be treated as preserving non-nullness,
249// regardless of how well the underlying StoreManager reasons about pointer
250// arithmetic.
251// <rdar://problem/6777209>
252void rdar_6777209(char *p) {
253  if (p == 0)
254    return;
255  
256  ++p;
257  
258  // This branch should always be infeasible.
259  if (p == 0)
260    *p = 'c'; // no-warning
261}
262
263// PR 4033.  A symbolic 'void *' pointer can be used as the address for a
264// computed goto.
265typedef void *Opcode;
266Opcode pr_4033_getOpcode();
267void pr_4033(void) {
268next_opcode:
269  {
270    Opcode op = pr_4033_getOpcode();
271    if (op) goto *op;
272  }
273}
274
275// Test invalidating pointers-to-pointers with slightly different types.  This
276// example came from a recent false positive due to a regression where the
277// branch condition was falsely reported as being uninitialized.
278void invalidate_by_ref(char **x);
279int test_invalidate_by_ref() {
280  unsigned short y;
281  invalidate_by_ref((char**) &y);
282  if (y) // no-warning
283    return 1;
284  return 0;  
285}
286
287// Test for <rdar://problem/7027684>.  This just tests that the CFG is
288// constructed correctly.  Previously, the successor block of the entrance
289// was the block containing the merge for '?', which would trigger an
290// assertion failure.
291int rdar_7027684_aux();
292int rdar_7027684_aux_2() __attribute__((noreturn));
293void rdar_7027684(int x, int y) {
294  {}; // this empty compound statement is critical.
295  (rdar_7027684_aux() ? rdar_7027684_aux_2() : (void) 0);
296}
297
298// Test that we handle casts of string literals to arbitrary types.
299unsigned const char *string_literal_test1() {
300  return (const unsigned char*) "hello";
301}
302
303const float *string_literal_test2() {
304  return (const float*) "hello";
305}
306
307// Test that we handle casts *from* incomplete struct types.
308extern const struct _FooAssertStruct _cmd;
309void test_cast_from_incomplete_struct_aux(volatile const void *x);
310void test_cast_from_incomplete_struct() {
311  test_cast_from_incomplete_struct_aux(&_cmd);
312}
313
314// Test for <rdar://problem/7034511> 
315//  "ValueManager::makeIntVal(uint64_t X, QualType T) should return a 'Loc' 
316//   when 'T' is a pointer"
317//
318// Previously this case would crash.
319void test_rdar_7034511(NSArray *y) {
320  NSObject *x;
321  for (x in y) {}
322  if (x == ((void*) 0)) {}
323}
324
325// Handle casts of function pointers (CodeTextRegions) to arbitrary pointer
326// types. This was previously causing a crash in CastRegion.
327void handle_funcptr_voidptr_casts() {
328  void **ptr;
329  typedef void *PVOID;
330  typedef void *PCHAR;  
331  typedef long INT_PTR, *PINT_PTR;
332  typedef INT_PTR (*FARPROC)();
333  FARPROC handle_funcptr_voidptr_casts_aux();
334  PVOID handle_funcptr_voidptr_casts_aux_2(PVOID volatile *x);
335  PVOID handle_funcptr_voidptr_casts_aux_3(PCHAR volatile *x);  
336  
337  ptr = (void**) handle_funcptr_voidptr_casts_aux();
338  handle_funcptr_voidptr_casts_aux_2(ptr);
339  handle_funcptr_voidptr_casts_aux_3(ptr);
340}
341
342// RegionStore::Retrieve previously crashed on this example.  This example
343// was previously in the test file 'xfail_regionstore_wine_crash.c'.
344void testA() {
345  long x = 0;
346  char *y = (char *) &x;
347  if (!*y)
348    return;
349}
350
351// RegionStoreManager previously crashed on this example.  The problem is that
352// the value bound to the field of b->grue after the call to testB_aux is
353// a symbolic region.  The second '*__gruep__' involves performing a load
354// from a 'int*' that really is a 'void**'.  The loaded location must be
355// implicitly converted to an integer that wraps a location.  Previosly we would
356// get a crash here due to an assertion failure.
357typedef struct _BStruct { void *grue; } BStruct;
358void testB_aux(void *ptr);
359void testB(BStruct *b) {
360  {
361    int *__gruep__ = ((int *)&((b)->grue));
362    int __gruev__ = *__gruep__;
363    testB_aux(__gruep__);
364  }
365  {
366    int *__gruep__ = ((int *)&((b)->grue));
367    int __gruev__ = *__gruep__;
368    if (~0 != __gruev__) {}
369  }
370}
371
372void test_trivial_symbolic_comparison(int *x) {
373  int test_trivial_symbolic_comparison_aux();
374  int a = test_trivial_symbolic_comparison_aux();
375  int b = a;
376  if (a != b) {
377    int *p = 0;
378    *p = 0xDEADBEEF;     // no-warning
379  }
380  
381  a = a == 1;
382  b = b == 1;
383  if (a != b) {
384    int *p = 0;
385    *p = 0xDEADBEEF;     // no-warning
386  }
387}
388
389// Test for:
390//  <rdar://problem/7062158> false positive null dereference due to
391//   BasicStoreManager not tracking *static* globals
392//
393// This just tests the proper tracking of symbolic values for globals (both 
394// static and non-static).
395//
396static int* x_rdar_7062158;
397void rdar_7062158() {
398  int *current = x_rdar_7062158;
399  if (current == x_rdar_7062158)
400    return;
401    
402  int *p = 0;
403  *p = 0xDEADBEEF; // no-warning  
404}
405
406int* x_rdar_7062158_2;
407void rdar_7062158_2() {
408  int *current = x_rdar_7062158_2;
409  if (current == x_rdar_7062158_2)
410    return;
411    
412  int *p = 0;
413  *p = 0xDEADBEEF; // no-warning  
414}
415
416// This test reproduces a case for a crash when analyzing ClamAV using
417// RegionStoreManager (the crash doesn't exhibit in BasicStoreManager because
418// it isn't doing anything smart about arrays).  The problem is that on the
419// second line, 'p = &p[i]', p is assigned an ElementRegion whose index
420// is a 16-bit integer.  On the third line, a new ElementRegion is created
421// based on the previous region, but there the region uses a 32-bit integer,
422// resulting in a clash of values (an assertion failure at best).  We resolve
423// this problem by implicitly converting index values to 'int' when the
424// ElementRegion is created.
425unsigned char test_array_index_bitwidth(const unsigned char *p) {
426  unsigned short i = 0;
427  for (i = 0; i < 2; i++) p = &p[i];  
428  return p[i+1];
429}
430
431// This case tests that CastRegion handles casts involving BlockPointerTypes.
432// It should not crash.
433void test_block_cast() {
434  id test_block_cast_aux();
435  (void (^)(void *))test_block_cast_aux(); // expected-warning{{expression result unused}}
436}
437
438// Test comparison of 'id' instance variable to a null void* constant after
439// performing an OSAtomicCompareAndSwap32Barrier.
440// This previously was a crash in RegionStoreManager.
441@interface TestIdNull {
442  id x;
443}
444-(int)foo;
445@end
446@implementation TestIdNull
447-(int)foo {
448  OSAtomicCompareAndSwap32Barrier(0, (signed)2, (signed*)&x);  
449  if (x == (void*) 0) { return 0; }
450  return 1;
451}
452@end
453
454// PR 4594 - This was a crash when handling casts in SimpleSValuator.
455void PR4594() {
456  char *buf[1];
457  char **foo = buf;
458  *foo = "test";
459}
460
461// Test invalidation logic where an integer is casted to an array with a
462// different sign and then invalidated.
463void test_invalidate_cast_int() {
464  void test_invalidate_cast_int_aux(unsigned *i);
465  signed i;  
466  test_invalidate_cast_int_aux((unsigned*) &i);
467  if (i < 0)
468    return;
469}
470
471