misc-ps-region-store.m revision 8780679b02bea5ab6360f3f8ebf3b221aaeda93f
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