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