Ted Kremenek | 0c10699 | 2009-07-14 23:17:22 +0000 | [diff] [blame] | 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 |
Ted Kremenek | 2dabd42 | 2009-01-22 18:53:15 +0000 | [diff] [blame] | 3 | |
Ted Kremenek | aad45e0 | 2009-03-05 04:55:08 +0000 | [diff] [blame] | 4 | typedef struct objc_selector *SEL; |
| 5 | typedef signed char BOOL; |
| 6 | typedef int NSInteger; |
| 7 | typedef unsigned int NSUInteger; |
| 8 | typedef 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 |
| 15 | extern 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 |
| 24 | extern NSString * const NSConnectionReplyMode; |
| 25 | |
| 26 | |
Ted Kremenek | 2dabd42 | 2009-01-22 18:53:15 +0000 | [diff] [blame] | 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 |
Ted Kremenek | 2dabd42 | 2009-01-22 18:53:15 +0000 | [diff] [blame] | 35 | void checkaccess_union() { |
| 36 | int ret = 0, status; |
Ted Kremenek | d4e5a60 | 2009-08-06 21:43:54 +0000 | [diff] [blame^] | 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 |
Ted Kremenek | 2dabd42 | 2009-01-22 18:53:15 +0000 | [diff] [blame] | 41 | __typeof (status) __in; int __i;} |
| 42 | ) |
| 43 | { |
| 44 | .__in = (status)} |
| 45 | ).__i))) & 0xff00) >> 8) == 1) |
| 46 | ret = 1; |
| 47 | } |
Ted Kremenek | d104a09 | 2009-03-04 22:56:43 +0000 | [diff] [blame] | 48 | |
Ted Kremenek | d104a09 | 2009-03-04 22:56:43 +0000 | [diff] [blame] | 49 | // Check our handling of fields being invalidated by function calls. |
| 50 | struct test2_struct { int x; int y; char* s; }; |
| 51 | void test2_helper(struct test2_struct* p); |
| 52 | |
| 53 | char 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 | } |
Ted Kremenek | aad45e0 | 2009-03-05 04:55:08 +0000 | [diff] [blame] | 72 | |
Ted Kremenek | 54ca9b1 | 2009-07-13 21:55:12 +0000 | [diff] [blame] | 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'. |
| 77 | void 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 | |
Ted Kremenek | 60fbe8f | 2009-07-14 20:48:22 +0000 | [diff] [blame] | 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. |
| 89 | typedef struct _BStruct { void *grue; } BStruct; |
| 90 | void testB_aux(void *ptr); |
Ted Kremenek | 0c10699 | 2009-07-14 23:17:22 +0000 | [diff] [blame] | 91 | |
Ted Kremenek | 60fbe8f | 2009-07-14 20:48:22 +0000 | [diff] [blame] | 92 | void testB(BStruct *b) { |
Ted Kremenek | a6275a5 | 2009-07-15 02:31:43 +0000 | [diff] [blame] | 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 | } |
Ted Kremenek | 60fbe8f | 2009-07-14 20:48:22 +0000 | [diff] [blame] | 115 | } |
| 116 | |
| 117 | void 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 | } |
Ted Kremenek | 386af0a | 2009-07-18 05:02:33 +0000 | [diff] [blame] | 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. |
| 136 | void test_declstmt_caching() { |
| 137 | again: |
| 138 | { |
| 139 | const char a[] = "I like to crash"; |
| 140 | goto again; |
| 141 | } |
| 142 | } |
Ted Kremenek | 28ba10c | 2009-08-03 22:23:24 +0000 | [diff] [blame] | 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. |
| 147 | struct s_7114618 { int *p; }; |
| 148 | void 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 | } |
Zhongxing Xu | bfc8168 | 2009-08-05 03:45:09 +0000 | [diff] [blame] | 158 | |
| 159 | // Test pointers increment correctly. |
| 160 | void 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 | } |