208 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
| // RUN: %clang_cc1  -triple x86_64-apple-darwin11 -fsyntax-only -verify %s -Wno-objc-root-class
 | |
| 
 | |
| // Mark this protocol as requiring all of its methods and properties
 | |
| // to be explicitly implemented in the adopting class.
 | |
| __attribute__((objc_protocol_requires_explicit_implementation))
 | |
| @protocol Protocol
 | |
| - (void) theBestOfTimes; // expected-note {{method 'theBestOfTimes' declared here}}
 | |
| @property (readonly) id theWorstOfTimes; // expected-note {{property declared here}} 
 | |
| @end
 | |
| 
 | |
| // In this example, ClassA adopts the protocol.  We won't
 | |
| // provide the implementation here, but this protocol will
 | |
| // be adopted later by a subclass.
 | |
| @interface ClassA <Protocol>
 | |
| - (void) theBestOfTimes;
 | |
| @property (readonly) id theWorstOfTimes; // expected-note {{property declared here}}
 | |
| @end
 | |
| 
 | |
| // This class subclasses ClassA (which also adopts 'Protocol').
 | |
| @interface ClassB : ClassA <Protocol>
 | |
| @end
 | |
| 
 | |
| @implementation ClassB // expected-warning {{property 'theWorstOfTimes' requires method 'theWorstOfTimes' to be defined - use @synthesize, @dynamic or provide a method implementation in this class implementation}} 
 | |
| @end
 | |
| 
 | |
| @interface ClassB_Good : ClassA <Protocol>
 | |
| @end
 | |
| 
 | |
| @implementation ClassB_Good // no-warning
 | |
| - (void) theBestOfTimes {}
 | |
| @dynamic theWorstOfTimes;
 | |
| @end
 | |
| 
 | |
| @interface ClassB_AlsoGood : ClassA <Protocol>
 | |
| @property (readonly) id theWorstOfTimes; // expected-warning {{auto property synthesis will not synthesize property 'theWorstOfTimes'; it will be implemented by its superclass}}
 | |
| @end
 | |
| 
 | |
| // Default synthesis acts as if @dynamic
 | |
| // had been written for 'theWorstOfTimes' because
 | |
| // it is declared in ClassA.  This is okay, since
 | |
| // the author of ClassB_AlsoGood needs explicitly
 | |
| // write @property in the @interface.
 | |
| @implementation ClassB_AlsoGood  // expected-note {{detected while default synthesizing properties in class implementation}}
 | |
| - (void) theBestOfTimes {}
 | |
| @end
 | |
| 
 | |
| // Test that inherited protocols do not get the explicit conformance requirement.
 | |
| @protocol Inherited
 | |
| - (void) fairIsFoul;
 | |
| @end
 | |
| 
 | |
| __attribute__((objc_protocol_requires_explicit_implementation))
 | |
| @protocol Derived <Inherited>
 | |
| - (void) foulIsFair; // expected-note {{method 'foulIsFair' declared here}}
 | |
| @end
 | |
| 
 | |
| @interface ClassC <Inherited>
 | |
| @end
 | |
| 
 | |
| @interface ClassD : ClassC <Derived>
 | |
| @end
 | |
| 
 | |
| @implementation ClassD // expected-warning {{method 'foulIsFair' in protocol 'Derived' not implemented}}
 | |
| @end
 | |
| 
 | |
| // Test that the attribute is used correctly.
 | |
| __attribute__((objc_protocol_requires_explicit_implementation(1+2))) // expected-error {{attribute takes no arguments}}
 | |
| @protocol AnotherProtocol @end
 | |
| 
 | |
| // Cannot put the attribute on classes or other non-protocol declarations.
 | |
| __attribute__((objc_protocol_requires_explicit_implementation)) // expected-error {{attribute only applies to Objective-C protocols}}
 | |
| @interface AnotherClass @end
 | |
| 
 | |
| __attribute__((objc_protocol_requires_explicit_implementation)) // expected-error {{attribute only applies to Objective-C protocols}}
 | |
| int x;
 | |
| 
 | |
| // Test that inherited protocols with the attribute
 | |
| // are treated properly.
 | |
| __attribute__((objc_protocol_requires_explicit_implementation))
 | |
| @protocol ProtocolA
 | |
| @required
 | |
| - (void)rlyeh; // expected-note 2 {{method 'rlyeh' declared here}}
 | |
| - (void)innsmouth; // expected-note 2 {{method 'innsmouth' declared here}}
 | |
| @end
 | |
| 
 | |
| @protocol ProtocolB <ProtocolA>
 | |
| @required
 | |
| - (void)dunwich;
 | |
| - (void)innsmouth; // expected-note {{method 'innsmouth' declared here}}
 | |
| @end
 | |
| 
 | |
| __attribute__((objc_protocol_requires_explicit_implementation))
 | |
| @protocol ProtocolB_Explicit <ProtocolA>
 | |
| @required
 | |
| - (void)dunwich;
 | |
| - (void)innsmouth; // expected-note 2 {{method 'innsmouth' declared here}}
 | |
| @end
 | |
| 
 | |
| @protocol ProtocolC
 | |
| @required
 | |
| - (void)rlyeh;
 | |
| - (void)innsmouth;
 | |
| - (void)dunwich;
 | |
| @end
 | |
| 
 | |
| @interface MyObject <ProtocolC> @end
 | |
| 
 | |
| // Provide two variants of a base class, one that adopts ProtocolA and
 | |
| // one that does not.
 | |
| @interface Lovecraft <ProtocolA> @end
 | |
| @interface Lovecraft_2 @end
 | |
| 
 | |
| // Provide two variants of a subclass that conform to ProtocolB.  One
 | |
| // subclasses from a class that conforms to ProtocolA, the other that
 | |
| // does not.
 | |
| //
 | |
| // From those, provide two variants that conformat to ProtocolB_Explicit
 | |
| // instead.
 | |
| @interface Shoggoth : Lovecraft <ProtocolB> @end
 | |
| @interface Shoggoth_2 : Lovecraft_2 <ProtocolB> @end
 | |
| @interface Shoggoth_Explicit : Lovecraft <ProtocolB_Explicit> @end
 | |
| @interface Shoggoth_2_Explicit : Lovecraft_2 <ProtocolB_Explicit> @end
 | |
| 
 | |
| @implementation MyObject
 | |
| - (void)innsmouth {}
 | |
| - (void)rlyeh {}
 | |
| - (void)dunwich {}
 | |
| @end
 | |
| 
 | |
| @implementation Lovecraft
 | |
| - (void)innsmouth {}
 | |
| - (void)rlyeh {}
 | |
| @end
 | |
| 
 | |
| @implementation Shoggoth
 | |
| - (void)dunwich {}
 | |
| @end
 | |
| 
 | |
| @implementation Shoggoth_2 // expected-warning {{method 'innsmouth' in protocol 'ProtocolB' not implemented}}\
 | |
|                            // expected-warning {{method 'rlyeh' in protocol 'ProtocolA' not implemented}}\
 | |
|                            // expected-warning {{'innsmouth' in protocol 'ProtocolA' not implemented}} 
 | |
| - (void)dunwich {}
 | |
| @end
 | |
| 
 | |
| @implementation Shoggoth_Explicit // expected-warning {{method 'innsmouth' in protocol 'ProtocolB_Explicit' not implemented}}
 | |
| - (void)dunwich {}
 | |
| @end
 | |
| 
 | |
| @implementation Shoggoth_2_Explicit // expected-warning {{method 'innsmouth' in protocol 'ProtocolB_Explicit' not implemented}}\
 | |
|                                     // expected-warning {{method 'rlyeh' in protocol 'ProtocolA' not implemented}}\
 | |
|                                     // expected-warning {{method 'innsmouth' in protocol 'ProtocolA' not implemented}}
 | |
| - (void)dunwich {}
 | |
| @end
 | |
| 
 | |
| // Categories adopting a protocol with explicit conformance need to implement that protocol.
 | |
| @interface Parent
 | |
| - (void) theBestOfTimes;
 | |
| @property (readonly) id theWorstOfTimes;
 | |
| @end
 | |
| 
 | |
| @interface Derived : Parent
 | |
| @end
 | |
| 
 | |
| @interface Derived (MyCat) <Protocol>
 | |
| @end
 | |
| 
 | |
| @implementation Derived (MyCat) // expected-warning {{method 'theBestOfTimes' in protocol 'Protocol' not implemented}}
 | |
| @end
 | |
| 
 | |
| __attribute__((objc_protocol_requires_explicit_implementation))  // expected-error{{attribute 'objc_protocol_requires_explicit_implementation' can only be applied to @protocol definitions, not forward declarations}}
 | |
| @protocol NotDefined;
 | |
| 
 | |
| // Another complete hierarchy.
 | |
|  __attribute__((objc_protocol_requires_explicit_implementation))
 | |
| @protocol Ex2FooBar
 | |
| - (void)methodA;
 | |
| @end
 | |
| 
 | |
|  __attribute__((objc_protocol_requires_explicit_implementation))
 | |
| @protocol Ex2ProtocolA
 | |
| - (void)methodB;
 | |
| @end
 | |
| 
 | |
|  __attribute__((objc_protocol_requires_explicit_implementation))
 | |
| @protocol Ex2ProtocolB <Ex2ProtocolA>
 | |
| - (void)methodA; // expected-note {{method 'methodA' declared here}}
 | |
| @end
 | |
| 
 | |
| // NOT required
 | |
| @protocol Ex2ProtocolC <Ex2ProtocolA>
 | |
| - (void)methodB;
 | |
| - (void)methodA;
 | |
| @end
 | |
| 
 | |
| @interface Ex2ClassA <Ex2ProtocolC, Ex2FooBar>
 | |
| @end
 | |
| @implementation Ex2ClassA
 | |
| - (void)methodB {}
 | |
| - (void)methodA {}
 | |
| @end
 | |
| 
 | |
| @interface Ex2ClassB : Ex2ClassA <Ex2ProtocolB>
 | |
| @end
 | |
| 
 | |
| @implementation Ex2ClassB // expected-warning {{method 'methodA' in protocol 'Ex2ProtocolB' not implemented}}
 | |
| @end
 | |
| 
 |