Jordan Rose | 3cf9a72 | 2012-10-30 01:21:35 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=alpha.osx.cocoa.MissingSuperCall -verify -Wno-objc-root-class %s |
| 2 | |
Jordan Rose | e14999e | 2012-12-13 03:06:45 +0000 | [diff] [blame] | 3 | // Define used Classes |
Jordan Rose | 3cf9a72 | 2012-10-30 01:21:35 +0000 | [diff] [blame] | 4 | @protocol NSObject |
| 5 | - (id)retain; |
| 6 | - (oneway void)release; |
| 7 | @end |
| 8 | @interface NSObject <NSObject> {} |
| 9 | - (id)init; |
| 10 | + (id)alloc; |
| 11 | @end |
Jordan Rose | 3cf9a72 | 2012-10-30 01:21:35 +0000 | [diff] [blame] | 12 | typedef char BOOL; |
| 13 | typedef double NSTimeInterval; |
| 14 | typedef enum UIViewAnimationOptions { |
| 15 | UIViewAnimationOptionLayoutSubviews = 1 << 0 |
| 16 | } UIViewAnimationOptions; |
Jordan Rose | e14999e | 2012-12-13 03:06:45 +0000 | [diff] [blame] | 17 | @interface NSCoder : NSObject {} |
| 18 | @end |
Jordan Rose | 3cf9a72 | 2012-10-30 01:21:35 +0000 | [diff] [blame] | 19 | |
Jordan Rose | e14999e | 2012-12-13 03:06:45 +0000 | [diff] [blame] | 20 | // Define the Superclasses for our Checks |
Jordan Rose | 3cf9a72 | 2012-10-30 01:21:35 +0000 | [diff] [blame] | 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 |
Jordan Rose | e14999e | 2012-12-13 03:06:45 +0000 | [diff] [blame] | 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 |
Jordan Rose | 3cf9a72 | 2012-10-30 01:21:35 +0000 | [diff] [blame] | 49 | |
Jordan Rose | e14999e | 2012-12-13 03:06:45 +0000 | [diff] [blame] | 50 | // Checks |
| 51 | |
| 52 | // Do not warn if UIViewController/*Responder/NSDocument is not our superclass |
Jordan Rose | 3cf9a72 | 2012-10-30 01:21:35 +0000 | [diff] [blame] | 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 {} |
Jordan Rose | e14999e | 2012-12-13 03:06:45 +0000 | [diff] [blame] | 67 | - (BOOL)resignFirstResponder { return 0; } |
| 68 | - (void)restoreStateWithCoder:(NSCoder *)coder {} |
| 69 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder {} |
Jordan Rose | 3cf9a72 | 2012-10-30 01:21:35 +0000 | [diff] [blame] | 70 | @end |
| 71 | |
| 72 | // Warn if UIViewController is our superclass and we do not call super |
| 73 | @interface TestB : UIViewController {} |
| 74 | @end |
| 75 | @implementation TestB |
| 76 | |
| 77 | - (void)addChildViewController:(UIViewController *)childController { |
| 78 | int addChildViewController = 5; |
| 79 | for (int i = 0; i < addChildViewController; i++) |
| 80 | [self viewDidAppear:i]; |
| 81 | } // expected-warning {{The 'addChildViewController:' instance method in UIViewController subclass 'TestB' is missing a [super addChildViewController:] call}} |
| 82 | - (void)viewDidAppear:(BOOL)animated {} // expected-warning {{The 'viewDidAppear:' instance method in UIViewController subclass 'TestB' is missing a [super viewDidAppear:] call}} |
| 83 | - (void)viewDidDisappear:(BOOL)animated {} // expected-warning {{The 'viewDidDisappear:' instance method in UIViewController subclass 'TestB' is missing a [super viewDidDisappear:] call}} |
| 84 | - (void)viewDidUnload {} // expected-warning {{The 'viewDidUnload' instance method in UIViewController subclass 'TestB' is missing a [super viewDidUnload] call}} |
| 85 | - (void)viewDidLoad {} // expected-warning {{The 'viewDidLoad' instance method in UIViewController subclass 'TestB' is missing a [super viewDidLoad] call}} |
| 86 | - (void)viewWillUnload {} // expected-warning {{The 'viewWillUnload' instance method in UIViewController subclass 'TestB' is missing a [super viewWillUnload] call}} |
| 87 | - (void)viewWillAppear:(BOOL)animated {} // expected-warning {{The 'viewWillAppear:' instance method in UIViewController subclass 'TestB' is missing a [super viewWillAppear:] call}} |
| 88 | - (void)viewWillDisappear:(BOOL)animated {} // expected-warning {{The 'viewWillDisappear:' instance method in UIViewController subclass 'TestB' is missing a [super viewWillDisappear:] call}} |
| 89 | - (void)didReceiveMemoryWarning {} // expected-warning {{The 'didReceiveMemoryWarning' instance method in UIViewController subclass 'TestB' is missing a [super didReceiveMemoryWarning] call}} |
| 90 | - (void)removeFromParentViewController {} // expected-warning {{The 'removeFromParentViewController' instance method in UIViewController subclass 'TestB' is missing a [super removeFromParentViewController] call}} |
| 91 | |
| 92 | // Do not warn for methods were it shouldn't |
Jordan Rose | e14999e | 2012-12-13 03:06:45 +0000 | [diff] [blame] | 93 | - (void)shouldAutorotate {} |
Jordan Rose | 3cf9a72 | 2012-10-30 01:21:35 +0000 | [diff] [blame] | 94 | @end |
| 95 | |
| 96 | // Do not warn if UIViewController is our superclass but we did call super |
| 97 | @interface TestC : UIViewController {} |
| 98 | @end |
| 99 | @implementation TestC |
| 100 | |
| 101 | - (BOOL)methodReturningStuff { |
| 102 | return 1; |
| 103 | } |
| 104 | |
| 105 | - (void)methodDoingStuff { |
| 106 | [super removeFromParentViewController]; |
| 107 | } |
| 108 | |
| 109 | - (void)addChildViewController:(UIViewController *)childController { |
| 110 | [super addChildViewController:childController]; |
| 111 | } |
| 112 | |
| 113 | - (void)viewDidAppear:(BOOL)animated { |
| 114 | [super viewDidAppear:animated]; |
| 115 | } |
| 116 | |
| 117 | - (void)viewDidDisappear:(BOOL)animated { |
| 118 | [super viewDidDisappear:animated]; |
| 119 | } |
| 120 | |
| 121 | - (void)viewDidUnload { |
| 122 | [super viewDidUnload]; |
| 123 | } |
| 124 | |
| 125 | - (void)viewDidLoad { |
| 126 | [super viewDidLoad]; |
| 127 | } |
| 128 | |
| 129 | - (void)viewWillUnload { |
| 130 | [super viewWillUnload]; |
| 131 | } |
| 132 | |
| 133 | - (void)viewWillAppear:(BOOL)animated { |
| 134 | int i = 0; // Also don't start warning just because we do additional stuff |
| 135 | i++; |
| 136 | [self viewDidDisappear:i]; |
| 137 | [super viewWillAppear:animated]; |
| 138 | } |
| 139 | |
| 140 | - (void)viewWillDisappear:(BOOL)animated { |
| 141 | [super viewWillDisappear:[self methodReturningStuff]]; |
| 142 | } |
| 143 | |
| 144 | - (void)didReceiveMemoryWarning { |
| 145 | [super didReceiveMemoryWarning]; |
| 146 | } |
| 147 | |
| 148 | // We expect a warning here because at the moment the super-call can't be |
| 149 | // done from another method. |
| 150 | - (void)removeFromParentViewController { |
| 151 | [self methodDoingStuff]; |
| 152 | } // expected-warning {{The 'removeFromParentViewController' instance method in UIViewController subclass 'TestC' is missing a [super removeFromParentViewController] call}} |
| 153 | @end |
Jordan Rose | e14999e | 2012-12-13 03:06:45 +0000 | [diff] [blame] | 154 | |
| 155 | |
| 156 | // Do warn for UIResponder subclasses that don't call super |
| 157 | @interface TestD : UIResponder {} |
| 158 | @end |
| 159 | @implementation TestD |
| 160 | |
| 161 | - (BOOL)resignFirstResponder { |
| 162 | return 0; |
| 163 | } // expected-warning {{The 'resignFirstResponder' instance method in UIResponder subclass 'TestD' is missing a [super resignFirstResponder] call}} |
| 164 | @end |
| 165 | |
| 166 | // Do not warn for UIResponder subclasses that do the right thing |
| 167 | @interface TestE : UIResponder {} |
| 168 | @end |
| 169 | @implementation TestE |
| 170 | |
| 171 | - (BOOL)resignFirstResponder { |
| 172 | return [super resignFirstResponder]; |
| 173 | } |
| 174 | @end |
| 175 | |
| 176 | // Do warn for NSResponder subclasses that don't call super |
| 177 | @interface TestF : NSResponder {} |
| 178 | @end |
| 179 | @implementation TestF |
| 180 | |
| 181 | - (void)restoreStateWithCoder:(NSCoder *)coder { |
| 182 | } // expected-warning {{The 'restoreStateWithCoder:' instance method in NSResponder subclass 'TestF' is missing a [super restoreStateWithCoder:] call}} |
| 183 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { |
| 184 | } // expected-warning {{The 'encodeRestorableStateWithCoder:' instance method in NSResponder subclass 'TestF' is missing a [super encodeRestorableStateWithCoder:] call}} |
| 185 | @end |
| 186 | |
| 187 | // Do not warn for NSResponder subclasses that do the right thing |
| 188 | @interface TestG : NSResponder {} |
| 189 | @end |
| 190 | @implementation TestG |
| 191 | |
| 192 | - (void)restoreStateWithCoder:(NSCoder *)coder { |
| 193 | [super restoreStateWithCoder:coder]; |
| 194 | } |
| 195 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { |
| 196 | [super encodeRestorableStateWithCoder:coder]; |
| 197 | } |
| 198 | @end |
| 199 | |
| 200 | // Do warn for NSDocument subclasses that don't call super |
| 201 | @interface TestH : NSDocument {} |
| 202 | @end |
| 203 | @implementation TestH |
| 204 | |
| 205 | - (void)restoreStateWithCoder:(NSCoder *)coder { |
| 206 | } // expected-warning {{The 'restoreStateWithCoder:' instance method in NSDocument subclass 'TestH' is missing a [super restoreStateWithCoder:] call}} |
| 207 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { |
| 208 | } // expected-warning {{The 'encodeRestorableStateWithCoder:' instance method in NSDocument subclass 'TestH' is missing a [super encodeRestorableStateWithCoder:] call}} |
| 209 | @end |
| 210 | |
| 211 | // Do not warn for NSDocument subclasses that do the right thing |
| 212 | @interface TestI : NSDocument {} |
| 213 | @end |
| 214 | @implementation TestI |
| 215 | |
| 216 | - (void)restoreStateWithCoder:(NSCoder *)coder { |
| 217 | [super restoreStateWithCoder:coder]; |
| 218 | } |
| 219 | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { |
| 220 | [super encodeRestorableStateWithCoder:coder]; |
| 221 | } |
| 222 | @end |