141 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
| // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -fblocks -verify -Wno-objc-root-class %s
 | |
| 
 | |
| void clang_analyzer_eval(int);
 | |
| 
 | |
| @interface Root {
 | |
| @public
 | |
|   int uniqueID;
 | |
| }
 | |
| 
 | |
| - (void)refreshID;
 | |
| @end
 | |
| 
 | |
| void testInvalidation(Root *obj) {
 | |
|   int savedID = obj->uniqueID;
 | |
|   clang_analyzer_eval(savedID == obj->uniqueID); // expected-warning{{TRUE}}
 | |
| 
 | |
|   [obj refreshID];
 | |
|   clang_analyzer_eval(savedID == obj->uniqueID); // expected-warning{{UNKNOWN}}
 | |
| }
 | |
| 
 | |
| 
 | |
| @interface Child : Root
 | |
| @end
 | |
| 
 | |
| @implementation Child
 | |
| - (void)testSuperInvalidation {
 | |
|   int savedID = self->uniqueID;
 | |
|   clang_analyzer_eval(savedID == self->uniqueID); // expected-warning{{TRUE}}
 | |
| 
 | |
|   [super refreshID];
 | |
|   clang_analyzer_eval(savedID == self->uniqueID); // expected-warning{{UNKNOWN}}
 | |
| }
 | |
| @end
 | |
| 
 | |
| 
 | |
| @interface ManyIvars {
 | |
|   struct S { int a, b; } s;
 | |
|   int c;
 | |
|   int d;
 | |
| }
 | |
| @end
 | |
| 
 | |
| struct S makeS();
 | |
| 
 | |
| @implementation ManyIvars
 | |
| 
 | |
| - (void)testMultipleIvarInvalidation:(int)useConstraints {
 | |
|   if (useConstraints) {
 | |
|     if (s.a != 1) return;
 | |
|     if (s.b != 2) return;
 | |
|     if (c != 3) return;
 | |
|     if (d != 4) return;
 | |
|     return;
 | |
|   } else {
 | |
|     s.a = 1;
 | |
|     s.b = 2;
 | |
|     c = 3;
 | |
|     d = 4;
 | |
|   }
 | |
| 
 | |
|   clang_analyzer_eval(s.a == 1); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(s.b == 2); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(d == 4); // expected-warning{{TRUE}}
 | |
| 
 | |
|   d = 0;
 | |
| 
 | |
|   clang_analyzer_eval(s.a == 1); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(s.b == 2); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(d == 0); // expected-warning{{TRUE}}
 | |
| 
 | |
|   d = 4;
 | |
|   s = makeS();
 | |
| 
 | |
|   clang_analyzer_eval(s.a == 1); // expected-warning{{UNKNOWN}}
 | |
|   clang_analyzer_eval(s.b == 2); // expected-warning{{UNKNOWN}}
 | |
|   clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(d == 4); // expected-warning{{TRUE}}
 | |
| 
 | |
|   s.a = 1;
 | |
| 
 | |
|   clang_analyzer_eval(s.a == 1); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(s.b == 2); // expected-warning{{UNKNOWN}}
 | |
|   clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(d == 4); // expected-warning{{TRUE}}
 | |
| }
 | |
| 
 | |
| + (void)testMultipleIvarInvalidation:(int)useConstraints
 | |
|                            forObject:(ManyIvars *)obj {
 | |
|   if (useConstraints) {
 | |
|     if (obj->s.a != 1) return;
 | |
|     if (obj->s.b != 2) return;
 | |
|     if (obj->c != 3) return;
 | |
|     if (obj->d != 4) return;
 | |
|     return;
 | |
|   } else {
 | |
|     obj->s.a = 1;
 | |
|     obj->s.b = 2;
 | |
|     obj->c = 3;
 | |
|     obj->d = 4;
 | |
|   }
 | |
| 
 | |
|   clang_analyzer_eval(obj->s.a == 1); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(obj->s.b == 2); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(obj->c == 3); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(obj->d == 4); // expected-warning{{TRUE}}
 | |
| 
 | |
|   obj->d = 0;
 | |
| 
 | |
|   clang_analyzer_eval(obj->s.a == 1); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(obj->s.b == 2); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(obj->c == 3); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(obj->d == 0); // expected-warning{{TRUE}}
 | |
| 
 | |
|   obj->d = 4;
 | |
|   obj->s = makeS();
 | |
| 
 | |
|   clang_analyzer_eval(obj->s.a == 1); // expected-warning{{UNKNOWN}}
 | |
|   clang_analyzer_eval(obj->s.b == 2); // expected-warning{{UNKNOWN}}
 | |
|   clang_analyzer_eval(obj->c == 3); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(obj->d == 4); // expected-warning{{TRUE}}
 | |
| 
 | |
|   obj->s.a = 1;
 | |
| 
 | |
|   clang_analyzer_eval(obj->s.a == 1); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(obj->s.b == 2); // expected-warning{{UNKNOWN}}
 | |
|   clang_analyzer_eval(obj->c == 3); // expected-warning{{TRUE}}
 | |
|   clang_analyzer_eval(obj->d == 4); // expected-warning{{TRUE}}
 | |
| }
 | |
| 
 | |
| @end
 | |
| 
 | |
| 
 | |
| int testNull(Root *obj) {
 | |
|   if (obj) return 0;
 | |
| 
 | |
|   int *x = &obj->uniqueID;
 | |
|   return *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
 | |
| }
 | 
