misc-ps-region-store.m revision 95efe0f7fb2ff2d83f9e6f97d707a79370034d73
1// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s &&
2// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s
3
4typedef struct objc_selector *SEL;
5typedef signed char BOOL;
6typedef int NSInteger;
7typedef unsigned int NSUInteger;
8typedef struct _NSZone NSZone;
9@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
10@protocol NSObject  - (BOOL)isEqual:(id)object; @end
11@protocol NSCopying  - (id)copyWithZone:(NSZone *)zone; @end
12@protocol NSMutableCopying  - (id)mutableCopyWithZone:(NSZone *)zone; @end
13@protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder; @end
14@interface NSObject <NSObject> {} - (id)init; @end
15extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
16@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>
17- (NSUInteger)length;
18+ (id)stringWithUTF8String:(const char *)nullTerminatedCString;
19@end extern NSString * const NSBundleDidLoadNotification;
20@interface NSAssertionHandler : NSObject {}
21+ (NSAssertionHandler *)currentHandler;
22- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...;
23@end
24extern NSString * const NSConnectionReplyMode;
25
26
27//---------------------------------------------------------------------------
28// Test case 'checkaccess_union' differs for region store and basic store.
29// The basic store doesn't reason about compound literals, so the code
30// below won't fire an "uninitialized value" warning.
31//---------------------------------------------------------------------------
32
33// PR 2948 (testcase; crash on VisitLValue for union types)
34// http://llvm.org/bugs/show_bug.cgi?id=2948
35void checkaccess_union() {
36  int ret = 0, status;
37  // Since RegionStore doesn't handle unions yet,
38  // this branch condition won't be triggered
39  // as involving an uninitialized value.  
40  if (((((__extension__ (((union {  // no-warning
41    __typeof (status) __in; int __i;}
42    )
43    {
44      .__in = (status)}
45      ).__i))) & 0xff00) >> 8) == 1)
46        ret = 1;
47}
48
49// Check our handling of fields being invalidated by function calls.
50struct test2_struct { int x; int y; char* s; };
51void test2_helper(struct test2_struct* p);
52
53char test2() {
54  struct test2_struct s;
55  test2_help(&s);
56  char *p = 0;
57  
58  if (s.x > 1) {
59    if (s.s != 0) {
60      p = "hello";
61    }
62  }
63  
64  if (s.x > 1) {
65    if (s.s != 0) {
66      return *p;
67    }
68  }
69
70  return 'a';
71}
72
73// BasicStore handles this case incorrectly because it doesn't reason about
74// the value pointed to by 'x' and thus creates different symbolic values
75// at the declarations of 'a' and 'b' respectively.  RegionStore handles
76// it correctly. See the companion test in 'misc-ps-basic-store.m'.
77void test_trivial_symbolic_comparison_pointer_parameter(int *x) {
78  int a = *x;
79  int b = *x;
80  if (a != b) {
81    int *p = 0;
82    *p = 0xDEADBEEF;     // no-warning
83  }
84}
85
86// This is a modified test from 'misc-ps.m'.  Here we have the extra
87// NULL dereferences which are pruned out by RegionStore's symbolic reasoning
88// of fields.
89typedef struct _BStruct { void *grue; } BStruct;
90void testB_aux(void *ptr);
91
92void testB(BStruct *b) {
93  {
94    int *__gruep__ = ((int *)&((b)->grue));
95    int __gruev__ = *__gruep__;
96    int __gruev2__ = *__gruep__;
97    if (__gruev__ != __gruev2__) {
98      int *p = 0;
99      *p = 0xDEADBEEF; // no-warning
100    }
101
102    testB_aux(__gruep__);
103  }
104  {
105    int *__gruep__ = ((int *)&((b)->grue));
106    int __gruev__ = *__gruep__;
107    int __gruev2__ = *__gruep__;
108    if (__gruev__ != __gruev2__) {
109      int *p = 0;
110      *p = 0xDEADBEEF; // no-warning
111    }
112
113    if (~0 != __gruev__) {}
114  }
115}
116
117void testB_2(BStruct *b) {
118  {
119    int **__gruep__ = ((int **)&((b)->grue));
120    int *__gruev__ = *__gruep__;
121    testB_aux(__gruep__);
122  }
123  {
124    int **__gruep__ = ((int **)&((b)->grue));
125    int *__gruev__ = *__gruep__;
126    if ((int*)~0 != __gruev__) {}
127  }
128}
129
130// This test case is a reduced case of a caching bug discovered by an
131// assertion failure in RegionStoreManager::BindArray.  Essentially the
132// DeclStmt is evaluated twice, but on the second loop iteration the
133// engine caches out.  Previously a false transition would cause UnknownVal
134// to bind to the variable, firing an assertion failure.  This bug was fixed
135// in r76262.
136void test_declstmt_caching() {
137again:
138  {
139    const char a[] = "I like to crash";
140    goto again;
141  }
142}
143
144// Reduced test case from <rdar://problem/7114618>.
145// Basically a null check is performed on the field value, which is then
146// assigned to a variable and then checked again.
147struct s_7114618 { int *p; };
148void test_rdar_7114618(struct s_7114618 *s) {
149  if (s->p) {
150    int *p = s->p;
151    if (!p) {
152      // Infeasible
153      int *dead = 0;
154      *dead = 0xDEADBEEF; // no-warning
155    }
156  }
157}
158
159// Test pointers increment correctly.
160void f() {
161  int a[2];
162  a[1] = 3;
163  int *p = a;
164  p++;
165  if (*p != 3) {
166    int *q = 0;
167    *q = 3; // no-warning
168  }
169}
170
171// <rdar://problem/7185607>
172// Bit-fields of a struct should be invalidated when blasting the entire
173// struct with an integer constant.
174struct test_7185607 {
175  int x : 10;
176  int y : 22;
177};
178int rdar_test_7185607() {
179  struct test_7185607 s; // Uninitialized.
180  *((unsigned *) &s) = 0U;
181  return s.x; // no-warning
182}
183
184// <rdar://problem/7242006> [RegionStore] compound literal assignment with
185//  floats not honored
186// This test case is mirrored in misc-ps.m, but this case is a negative.
187typedef float CGFloat;
188typedef struct _NSSize {
189    CGFloat width;
190    CGFloat height;
191} NSSize;
192
193CGFloat rdar7242006_negative(CGFloat x) {
194  NSSize y;
195  return y.width; // expected-warning{{garbage}}
196}
197
198// <rdar://problem/7249340> - Allow binding of values to symbolic regions.
199// This test case shows how RegionStore tracks the value bound to 'x'
200// after the assignment.
201typedef int* ptr_rdar_7249340;
202void rdar_7249340(ptr_rdar_7249340 x) {
203  *x = 1;
204  if (*x)
205    return;
206  int *p = 0;   // This is unreachable.
207  *p = 0xDEADBEEF; // no-warning
208}
209
210// <rdar://problem/7249327> - This test case tests both value tracking of
211// array values and that we handle symbolic values that are casted
212// between different integer types.  Note the assignment 'n = *a++'; here
213// 'n' is and 'int' and '*a' is 'unsigned'.  Previously we got a false positive
214// at 'x += *b++' (undefined value) because we got a false path.
215int rdar_7249327_aux(void);
216
217void rdar_7249327(unsigned int A[2*32]) {
218  int B[2*32];
219  int *b;
220  unsigned int *a;
221  int x = 0;
222  
223  int n;
224  
225  a = A;
226  b = B;
227  
228  n = *a++;
229  if (n)
230    *b++ = rdar_7249327_aux();
231
232  a = A;
233  b = B;
234  
235  n = *a++;
236  if (n)
237    x += *b++; // no-warning
238}
239
240// <rdar://problem/6914474> - Check that 'x' is invalidated because its
241// address is passed in as a value to a struct.
242struct doodad_6914474 { int *v; };
243extern void prod_6914474(struct doodad_6914474 *d);
244int rdar_6914474(void) {
245  int x;
246  struct doodad_6914474 d;
247  d.v = &x;
248  prod_6914474(&d);
249  return x; // no-warning
250}
251
252// Test invalidation of a single field.
253struct s_test_field_invalidate {
254  int x;
255};
256extern void test_invalidate_field(int *x);
257int test_invalidate_field_test() {
258  struct s_test_field_invalidate y;
259  test_invalidate_field(&y.x);
260  return y.x; // no-warning
261}
262int test_invalidate_field_test_positive() {
263  struct s_test_field_invalidate y;
264  return y.x; // expected-warning{{garbage}}
265}
266
267// This test case illustrates how a typeless array of bytes casted to a
268// struct should be treated as initialized.  RemoveDeadBindings previously
269// had a bug that caused 'x' to lose its default symbolic value after the
270// assignment to 'p', thus causing 'p->z' to evaluate to "undefined".
271struct ArrayWrapper { unsigned char y[16]; };
272struct WrappedStruct { unsigned z; };
273
274int test_handle_array_wrapper() {
275  struct ArrayWrapper x;
276  test_handle_array_wrapper(&x);
277  struct WrappedStruct *p = (struct WrappedStruct*) x.y;
278  return p->z;  // no-warning
279}
280
281// <rdar://problem/7261075> [RegionStore] crash when 
282//   handling load: '*((unsigned int *)"????")'
283int rdar_7261075(void) {
284  unsigned int var = 0;
285  if (var == *((unsigned int *)"????"))
286    return 1;
287  return 0;
288}
289
290