ObjCDynTypePopagation.m revision c4c647c88ced2e953f15f8987952ede9b96aa969
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=dynamic -verify %s
2
3typedef signed char BOOL;
4
5void clang_analyzer_eval(BOOL);
6
7@protocol NSObject  - (BOOL)isEqual:(id)object; @end
8@interface NSObject <NSObject> {}
9+(id)alloc;
10-(id)init;
11+(id)new;
12-(id)autorelease;
13-(id)copy;
14- (Class)class;
15-(id)retain;
16@end
17
18@interface MyParent : NSObject
19- (int)getZeroOverridden;
20@end
21@implementation MyParent
22- (int) getZeroOverridden {
23   return 1;
24}
25- (int) getZero {
26   return 0;
27}
28@end
29
30@interface MyClass : MyParent
31- (int) getZeroOverridden;
32@end
33
34MyClass *getObj();
35
36@implementation MyClass
37- (int) getZeroOverridden {
38   return 0;
39}
40
41/* Test that we get the right type from call to alloc. */
42
43+ (void) testAllocSelf {
44  id a = [self alloc];
45  clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
46}
47
48
49+ (void) testAllocClass {
50  id a = [MyClass alloc];
51  clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
52}
53
54+ (void) testAllocSuperOverriden {
55  id a = [super alloc];
56  // Evaluates to 1 in the parent.
57  clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{FALSE}} 
58}
59
60+ (void) testAllocSuper {
61  id a = [super alloc];
62  clang_analyzer_eval([a getZero] == 0); // expected-warning{{TRUE}}
63}
64
65+ (void) testAllocInit {
66  id a = [[self alloc] init];
67  clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
68}
69
70+ (void) testNewSelf {
71  id a = [self new];
72  clang_analyzer_eval([a getZeroOverridden] == 0); // expected-warning{{TRUE}}
73}
74
75// Casting to parent should not pessimize the dynamic type. 
76+ (void) testCastToParent {
77 id a = [[self alloc] init];
78  MyParent *p = a;  
79  clang_analyzer_eval([p getZeroOverridden] == 0); // expected-warning{{TRUE}}
80}
81
82// The type of parameter gets used.
83+ (void)testTypeFromParam:(MyParent*) p {
84  clang_analyzer_eval([p getZero] == 0); // expected-warning{{TRUE}}
85}
86
87// Test implisit cast.
88+ (void) testCastFromId:(id) a {
89  MyParent *p = a;  
90  clang_analyzer_eval([p getZero] == 0); // expected-warning{{TRUE}}
91}
92
93@end