1 | // RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=osx.cocoa.MissingSuperCall -verify -Wno-objc-root-class %s |
2 | |
3 | // Define used Classes |
4 | @protocol NSObject |
5 | - (id)retain; |
6 | - (oneway void)release; |
7 | @end |
8 | @interface NSObject <NSObject> {} |
9 | - (id)init; |
10 | + (id)alloc; |
11 | @end |
12 | typedef char BOOL; |
13 | typedef double NSTimeInterval; |
14 | typedef enum UIViewAnimationOptions { |
15 | UIViewAnimationOptionLayoutSubviews = 1 << 0 |
16 | } UIViewAnimationOptions; |
17 | @interface NSCoder : NSObject {} |
18 | @end |
19 | |
20 | // Define the Superclasses for our Checks |
21 | @interface UIViewController : NSObject {} |
22 | - (void)addChildViewController:(UIViewController *)childController; |
23 | - (void)viewDidAppear:(BOOL)animated; |
24 | - (void)viewDidDisappear:(BOOL)animated; |
25 | - (void)viewDidUnload; |
26 | - (void)viewDidLoad; |
27 | - (void)viewWillUnload; |
28 | - (void)viewWillAppear:(BOOL)animated; |
29 | - (void)viewWillDisappear:(BOOL)animated; |
30 | - (void)didReceiveMemoryWarning; |
31 | - (void)removeFromParentViewController; |
32 | - (void)transitionFromViewController:(UIViewController *)fromViewController |
33 | toViewController:(UIViewController *)toViewController |
34 | duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options |
35 | animations:(void (^)(void))animations |
36 | completion:(void (^)(BOOL finished))completion; |
37 | @end |
38 | @interface UIResponder : NSObject {} |
39 | - (BOOL)resignFirstResponder; |
40 | @end |
41 | @interface NSResponder : NSObject {} |
42 | - (void)restoreStateWithCoder:(NSCoder *)coder; |
43 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder; |
44 | @end |
45 | @interface NSDocument : NSObject {} |
46 | - (void)restoreStateWithCoder:(NSCoder *)coder; |
47 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder; |
48 | @end |
49 | |
50 | // Checks |
51 | |
52 | // Do not warn if UIViewController/*Responder/NSDocument is not our superclass |
53 | @interface TestA |
54 | @end |
55 | @implementation TestA |
56 | |
57 | - (void)addChildViewController:(UIViewController *)childController {} |
58 | - (void)viewDidAppear:(BOOL)animated {} |
59 | - (void)viewDidDisappear:(BOOL)animated {} |
60 | - (void)viewDidUnload {} |
61 | - (void)viewDidLoad {} |
62 | - (void)viewWillUnload {} |
63 | - (void)viewWillAppear:(BOOL)animated {} |
64 | - (void)viewWillDisappear:(BOOL)animated {} |
65 | - (void)didReceiveMemoryWarning {} |
66 | - (void)removeFromParentViewController {} |
67 | - (BOOL)resignFirstResponder { return 0; } |
68 | - (void)restoreStateWithCoder:(NSCoder *)coder {} |
69 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder {} |
70 | @end |
71 | |
72 | // Do not warn for the implementation in the superclass itself. |
73 | @implementation UIViewController |
74 | - (void)addChildViewController:(UIViewController *)childController {} |
75 | - (void)viewDidAppear:(BOOL)animated {} |
76 | - (void)viewDidDisappear:(BOOL)animated {} |
77 | - (void)viewDidUnload {} |
78 | - (void)viewDidLoad {} |
79 | - (void)viewWillUnload {} |
80 | - (void)viewWillAppear:(BOOL)animated {} |
81 | - (void)viewWillDisappear:(BOOL)animated {} |
82 | - (void)didReceiveMemoryWarning {} |
83 | - (void)removeFromParentViewController {} |
84 | - (void)transitionFromViewController:(UIViewController *)fromViewController |
85 | toViewController:(UIViewController *)toViewController |
86 | duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options |
87 | animations:(void (^)(void))animations |
88 | completion:(void (^)(BOOL finished))completion {} |
89 | @end |
90 | |
91 | // Warn if UIViewController is our superclass and we do not call super |
92 | @interface TestB : UIViewController {} |
93 | @end |
94 | @implementation TestB |
95 | |
96 | - (void)addChildViewController:(UIViewController *)childController { |
97 | int addChildViewController = 5; |
98 | for (int i = 0; i < addChildViewController; i++) |
99 | [self viewDidAppear:i]; |
100 | } // expected-warning {{The 'addChildViewController:' instance method in UIViewController subclass 'TestB' is missing a [super addChildViewController:] call}} |
101 | - (void)viewDidAppear:(BOOL)animated {} // expected-warning {{The 'viewDidAppear:' instance method in UIViewController subclass 'TestB' is missing a [super viewDidAppear:] call}} |
102 | - (void)viewDidDisappear:(BOOL)animated {} // expected-warning {{The 'viewDidDisappear:' instance method in UIViewController subclass 'TestB' is missing a [super viewDidDisappear:] call}} |
103 | - (void)viewDidUnload {} // expected-warning {{The 'viewDidUnload' instance method in UIViewController subclass 'TestB' is missing a [super viewDidUnload] call}} |
104 | - (void)viewDidLoad {} // expected-warning {{The 'viewDidLoad' instance method in UIViewController subclass 'TestB' is missing a [super viewDidLoad] call}} |
105 | - (void)viewWillUnload {} // expected-warning {{The 'viewWillUnload' instance method in UIViewController subclass 'TestB' is missing a [super viewWillUnload] call}} |
106 | - (void)viewWillAppear:(BOOL)animated {} // expected-warning {{The 'viewWillAppear:' instance method in UIViewController subclass 'TestB' is missing a [super viewWillAppear:] call}} |
107 | - (void)viewWillDisappear:(BOOL)animated {} // expected-warning {{The 'viewWillDisappear:' instance method in UIViewController subclass 'TestB' is missing a [super viewWillDisappear:] call}} |
108 | - (void)didReceiveMemoryWarning {} // expected-warning {{The 'didReceiveMemoryWarning' instance method in UIViewController subclass 'TestB' is missing a [super didReceiveMemoryWarning] call}} |
109 | - (void)removeFromParentViewController {} // expected-warning {{The 'removeFromParentViewController' instance method in UIViewController subclass 'TestB' is missing a [super removeFromParentViewController] call}} |
110 | |
111 | // Do not warn for methods were it shouldn't |
112 | - (void)shouldAutorotate {} |
113 | @end |
114 | |
115 | // Do not warn if UIViewController is our superclass but we did call super |
116 | @interface TestC : UIViewController {} |
117 | @end |
118 | @implementation TestC |
119 | |
120 | - (BOOL)methodReturningStuff { |
121 | return 1; |
122 | } |
123 | |
124 | - (void)methodDoingStuff { |
125 | [super removeFromParentViewController]; |
126 | } |
127 | |
128 | - (void)addChildViewController:(UIViewController *)childController { |
129 | [super addChildViewController:childController]; |
130 | } |
131 | |
132 | - (void)viewDidAppear:(BOOL)animated { |
133 | [super viewDidAppear:animated]; |
134 | } |
135 | |
136 | - (void)viewDidDisappear:(BOOL)animated { |
137 | [super viewDidDisappear:animated]; |
138 | } |
139 | |
140 | - (void)viewDidUnload { |
141 | [super viewDidUnload]; |
142 | } |
143 | |
144 | - (void)viewDidLoad { |
145 | [super viewDidLoad]; |
146 | } |
147 | |
148 | - (void)viewWillUnload { |
149 | [super viewWillUnload]; |
150 | } |
151 | |
152 | - (void)viewWillAppear:(BOOL)animated { |
153 | int i = 0; // Also don't start warning just because we do additional stuff |
154 | i++; |
155 | [self viewDidDisappear:i]; |
156 | [super viewWillAppear:animated]; |
157 | } |
158 | |
159 | - (void)viewWillDisappear:(BOOL)animated { |
160 | [super viewWillDisappear:[self methodReturningStuff]]; |
161 | } |
162 | |
163 | - (void)didReceiveMemoryWarning { |
164 | [super didReceiveMemoryWarning]; |
165 | } |
166 | |
167 | // We expect a warning here because at the moment the super-call can't be |
168 | // done from another method. |
169 | - (void)removeFromParentViewController { |
170 | [self methodDoingStuff]; |
171 | } // expected-warning {{The 'removeFromParentViewController' instance method in UIViewController subclass 'TestC' is missing a [super removeFromParentViewController] call}} |
172 | @end |
173 | |
174 | |
175 | // Do warn for UIResponder subclasses that don't call super |
176 | @interface TestD : UIResponder {} |
177 | @end |
178 | @implementation TestD |
179 | |
180 | - (BOOL)resignFirstResponder { |
181 | return 0; |
182 | } // expected-warning {{The 'resignFirstResponder' instance method in UIResponder subclass 'TestD' is missing a [super resignFirstResponder] call}} |
183 | @end |
184 | |
185 | // Do not warn for UIResponder subclasses that do the right thing |
186 | @interface TestE : UIResponder {} |
187 | @end |
188 | @implementation TestE |
189 | |
190 | - (BOOL)resignFirstResponder { |
191 | return [super resignFirstResponder]; |
192 | } |
193 | @end |
194 | |
195 | // Do warn for NSResponder subclasses that don't call super |
196 | @interface TestF : NSResponder {} |
197 | @end |
198 | @implementation TestF |
199 | |
200 | - (void)restoreStateWithCoder:(NSCoder *)coder { |
201 | } // expected-warning {{The 'restoreStateWithCoder:' instance method in NSResponder subclass 'TestF' is missing a [super restoreStateWithCoder:] call}} |
202 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { |
203 | } // expected-warning {{The 'encodeRestorableStateWithCoder:' instance method in NSResponder subclass 'TestF' is missing a [super encodeRestorableStateWithCoder:] call}} |
204 | @end |
205 | |
206 | // Do not warn for NSResponder subclasses that do the right thing |
207 | @interface TestG : NSResponder {} |
208 | @end |
209 | @implementation TestG |
210 | |
211 | - (void)restoreStateWithCoder:(NSCoder *)coder { |
212 | [super restoreStateWithCoder:coder]; |
213 | } |
214 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { |
215 | [super encodeRestorableStateWithCoder:coder]; |
216 | } |
217 | @end |
218 | |
219 | // Do warn for NSDocument subclasses that don't call super |
220 | @interface TestH : NSDocument {} |
221 | @end |
222 | @implementation TestH |
223 | |
224 | - (void)restoreStateWithCoder:(NSCoder *)coder { |
225 | } // expected-warning {{The 'restoreStateWithCoder:' instance method in NSDocument subclass 'TestH' is missing a [super restoreStateWithCoder:] call}} |
226 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { |
227 | } // expected-warning {{The 'encodeRestorableStateWithCoder:' instance method in NSDocument subclass 'TestH' is missing a [super encodeRestorableStateWithCoder:] call}} |
228 | @end |
229 | |
230 | // Do not warn for NSDocument subclasses that do the right thing |
231 | @interface TestI : NSDocument {} |
232 | @end |
233 | @implementation TestI |
234 | |
235 | - (void)restoreStateWithCoder:(NSCoder *)coder { |
236 | [super restoreStateWithCoder:coder]; |
237 | } |
238 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { |
239 | [super encodeRestorableStateWithCoder:coder]; |
240 | } |
241 | @end |