1// RUN: %clang_cc1 -fblocks -analyze -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
12typedef char BOOL;
13typedef double NSTimeInterval;
14typedef 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