|  | // RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=osx.cocoa.MissingSuperCall -verify -Wno-objc-root-class %s | 
|  |  | 
|  | // Define used Classes | 
|  | @protocol NSObject | 
|  | - (id)retain; | 
|  | - (oneway void)release; | 
|  | @end | 
|  | @interface NSObject <NSObject> {} | 
|  | - (id)init; | 
|  | + (id)alloc; | 
|  | @end | 
|  | typedef char BOOL; | 
|  | typedef double NSTimeInterval; | 
|  | typedef enum UIViewAnimationOptions { | 
|  | UIViewAnimationOptionLayoutSubviews = 1 <<  0 | 
|  | } UIViewAnimationOptions; | 
|  | @interface NSCoder : NSObject {} | 
|  | @end | 
|  |  | 
|  | // Define the Superclasses for our Checks | 
|  | @interface UIViewController : NSObject {} | 
|  | - (void)addChildViewController:(UIViewController *)childController; | 
|  | - (void)viewDidAppear:(BOOL)animated; | 
|  | - (void)viewDidDisappear:(BOOL)animated; | 
|  | - (void)viewDidUnload; | 
|  | - (void)viewDidLoad; | 
|  | - (void)viewWillUnload; | 
|  | - (void)viewWillAppear:(BOOL)animated; | 
|  | - (void)viewWillDisappear:(BOOL)animated; | 
|  | - (void)didReceiveMemoryWarning; | 
|  | - (void)removeFromParentViewController; | 
|  | - (void)transitionFromViewController:(UIViewController *)fromViewController | 
|  | toViewController:(UIViewController *)toViewController | 
|  | duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options | 
|  | animations:(void (^)(void))animations | 
|  | completion:(void (^)(BOOL finished))completion; | 
|  | @end | 
|  | @interface UIResponder : NSObject {} | 
|  | - (BOOL)resignFirstResponder; | 
|  | @end | 
|  | @interface NSResponder : NSObject {} | 
|  | - (void)restoreStateWithCoder:(NSCoder *)coder; | 
|  | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder; | 
|  | @end | 
|  | @interface NSDocument : NSObject {} | 
|  | - (void)restoreStateWithCoder:(NSCoder *)coder; | 
|  | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder; | 
|  | @end | 
|  |  | 
|  | // Checks | 
|  |  | 
|  | // Do not warn if UIViewController/*Responder/NSDocument is not our superclass | 
|  | @interface TestA | 
|  | @end | 
|  | @implementation TestA | 
|  |  | 
|  | - (void)addChildViewController:(UIViewController *)childController {} | 
|  | - (void)viewDidAppear:(BOOL)animated {} | 
|  | - (void)viewDidDisappear:(BOOL)animated {} | 
|  | - (void)viewDidUnload {} | 
|  | - (void)viewDidLoad {} | 
|  | - (void)viewWillUnload {} | 
|  | - (void)viewWillAppear:(BOOL)animated {} | 
|  | - (void)viewWillDisappear:(BOOL)animated {} | 
|  | - (void)didReceiveMemoryWarning {} | 
|  | - (void)removeFromParentViewController {} | 
|  | - (BOOL)resignFirstResponder { return 0; } | 
|  | - (void)restoreStateWithCoder:(NSCoder *)coder {} | 
|  | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder {} | 
|  | @end | 
|  |  | 
|  | // Warn if UIViewController is our superclass and we do not call super | 
|  | @interface TestB : UIViewController {} | 
|  | @end | 
|  | @implementation TestB | 
|  |  | 
|  | - (void)addChildViewController:(UIViewController *)childController { | 
|  | int addChildViewController = 5; | 
|  | for (int i = 0; i < addChildViewController; i++) | 
|  | [self viewDidAppear:i]; | 
|  | } // expected-warning {{The 'addChildViewController:' instance method in UIViewController subclass 'TestB' is missing a [super addChildViewController:] call}} | 
|  | - (void)viewDidAppear:(BOOL)animated {} // expected-warning {{The 'viewDidAppear:' instance method in UIViewController subclass 'TestB' is missing a [super viewDidAppear:] call}} | 
|  | - (void)viewDidDisappear:(BOOL)animated {} // expected-warning {{The 'viewDidDisappear:' instance method in UIViewController subclass 'TestB' is missing a [super viewDidDisappear:] call}} | 
|  | - (void)viewDidUnload {} // expected-warning {{The 'viewDidUnload' instance method in UIViewController subclass 'TestB' is missing a [super viewDidUnload] call}} | 
|  | - (void)viewDidLoad {} // expected-warning {{The 'viewDidLoad' instance method in UIViewController subclass 'TestB' is missing a [super viewDidLoad] call}} | 
|  | - (void)viewWillUnload {} // expected-warning {{The 'viewWillUnload' instance method in UIViewController subclass 'TestB' is missing a [super viewWillUnload] call}} | 
|  | - (void)viewWillAppear:(BOOL)animated {} // expected-warning {{The 'viewWillAppear:' instance method in UIViewController subclass 'TestB' is missing a [super viewWillAppear:] call}} | 
|  | - (void)viewWillDisappear:(BOOL)animated {} // expected-warning {{The 'viewWillDisappear:' instance method in UIViewController subclass 'TestB' is missing a [super viewWillDisappear:] call}} | 
|  | - (void)didReceiveMemoryWarning {} // expected-warning {{The 'didReceiveMemoryWarning' instance method in UIViewController subclass 'TestB' is missing a [super didReceiveMemoryWarning] call}} | 
|  | - (void)removeFromParentViewController {} // expected-warning {{The 'removeFromParentViewController' instance method in UIViewController subclass 'TestB' is missing a [super removeFromParentViewController] call}} | 
|  |  | 
|  | // Do not warn for methods were it shouldn't | 
|  | - (void)shouldAutorotate {} | 
|  | @end | 
|  |  | 
|  | // Do not warn if UIViewController is our superclass but we did call super | 
|  | @interface TestC : UIViewController {} | 
|  | @end | 
|  | @implementation TestC | 
|  |  | 
|  | - (BOOL)methodReturningStuff { | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | - (void)methodDoingStuff { | 
|  | [super removeFromParentViewController]; | 
|  | } | 
|  |  | 
|  | - (void)addChildViewController:(UIViewController *)childController { | 
|  | [super addChildViewController:childController]; | 
|  | } | 
|  |  | 
|  | - (void)viewDidAppear:(BOOL)animated { | 
|  | [super viewDidAppear:animated]; | 
|  | } | 
|  |  | 
|  | - (void)viewDidDisappear:(BOOL)animated { | 
|  | [super viewDidDisappear:animated]; | 
|  | } | 
|  |  | 
|  | - (void)viewDidUnload { | 
|  | [super viewDidUnload]; | 
|  | } | 
|  |  | 
|  | - (void)viewDidLoad { | 
|  | [super viewDidLoad]; | 
|  | } | 
|  |  | 
|  | - (void)viewWillUnload { | 
|  | [super viewWillUnload]; | 
|  | } | 
|  |  | 
|  | - (void)viewWillAppear:(BOOL)animated { | 
|  | int i = 0; // Also don't start warning just because we do additional stuff | 
|  | i++; | 
|  | [self viewDidDisappear:i]; | 
|  | [super viewWillAppear:animated]; | 
|  | } | 
|  |  | 
|  | - (void)viewWillDisappear:(BOOL)animated { | 
|  | [super viewWillDisappear:[self methodReturningStuff]]; | 
|  | } | 
|  |  | 
|  | - (void)didReceiveMemoryWarning { | 
|  | [super didReceiveMemoryWarning]; | 
|  | } | 
|  |  | 
|  | // We expect a warning here because at the moment the super-call can't be | 
|  | // done from another method. | 
|  | - (void)removeFromParentViewController { | 
|  | [self methodDoingStuff]; | 
|  | } // expected-warning {{The 'removeFromParentViewController' instance method in UIViewController subclass 'TestC' is missing a [super removeFromParentViewController] call}} | 
|  | @end | 
|  |  | 
|  |  | 
|  | // Do warn for UIResponder subclasses that don't call super | 
|  | @interface TestD : UIResponder {} | 
|  | @end | 
|  | @implementation TestD | 
|  |  | 
|  | - (BOOL)resignFirstResponder { | 
|  | return 0; | 
|  | } // expected-warning {{The 'resignFirstResponder' instance method in UIResponder subclass 'TestD' is missing a [super resignFirstResponder] call}} | 
|  | @end | 
|  |  | 
|  | // Do not warn for UIResponder subclasses that do the right thing | 
|  | @interface TestE : UIResponder {} | 
|  | @end | 
|  | @implementation TestE | 
|  |  | 
|  | - (BOOL)resignFirstResponder { | 
|  | return [super resignFirstResponder]; | 
|  | } | 
|  | @end | 
|  |  | 
|  | // Do warn for NSResponder subclasses that don't call super | 
|  | @interface TestF : NSResponder {} | 
|  | @end | 
|  | @implementation TestF | 
|  |  | 
|  | - (void)restoreStateWithCoder:(NSCoder *)coder { | 
|  | } // expected-warning {{The 'restoreStateWithCoder:' instance method in NSResponder subclass 'TestF' is missing a [super restoreStateWithCoder:] call}} | 
|  | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { | 
|  | } // expected-warning {{The 'encodeRestorableStateWithCoder:' instance method in NSResponder subclass 'TestF' is missing a [super encodeRestorableStateWithCoder:] call}} | 
|  | @end | 
|  |  | 
|  | // Do not warn for NSResponder subclasses that do the right thing | 
|  | @interface TestG : NSResponder {} | 
|  | @end | 
|  | @implementation TestG | 
|  |  | 
|  | - (void)restoreStateWithCoder:(NSCoder *)coder { | 
|  | [super restoreStateWithCoder:coder]; | 
|  | } | 
|  | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { | 
|  | [super encodeRestorableStateWithCoder:coder]; | 
|  | } | 
|  | @end | 
|  |  | 
|  | // Do warn for NSDocument subclasses that don't call super | 
|  | @interface TestH : NSDocument {} | 
|  | @end | 
|  | @implementation TestH | 
|  |  | 
|  | - (void)restoreStateWithCoder:(NSCoder *)coder { | 
|  | } // expected-warning {{The 'restoreStateWithCoder:' instance method in NSDocument subclass 'TestH' is missing a [super restoreStateWithCoder:] call}} | 
|  | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { | 
|  | } // expected-warning {{The 'encodeRestorableStateWithCoder:' instance method in NSDocument subclass 'TestH' is missing a [super encodeRestorableStateWithCoder:] call}} | 
|  | @end | 
|  |  | 
|  | // Do not warn for NSDocument subclasses that do the right thing | 
|  | @interface TestI : NSDocument {} | 
|  | @end | 
|  | @implementation TestI | 
|  |  | 
|  | - (void)restoreStateWithCoder:(NSCoder *)coder { | 
|  | [super restoreStateWithCoder:coder]; | 
|  | } | 
|  | - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { | 
|  | [super encodeRestorableStateWithCoder:coder]; | 
|  | } | 
|  | @end |