// 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 - (void) theBestOfTimes; @property (readonly) id theWorstOfTimes; // expected-note {{property declared here}} @end // This class subclasses ClassA (which also adopts 'Protocol'). @interface ClassB : ClassA @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 @end @implementation ClassB_Good // no-warning - (void) theBestOfTimes {} @dynamic theWorstOfTimes; @end @interface ClassB_AlsoGood : ClassA @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 - (void) foulIsFair; // expected-note {{method 'foulIsFair' declared here}} @end @interface ClassC @end @interface ClassD : ClassC @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 @required - (void)dunwich; - (void)innsmouth; // expected-note {{method 'innsmouth' declared here}} @end __attribute__((objc_protocol_requires_explicit_implementation)) @protocol ProtocolB_Explicit @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 @end // Provide two variants of a base class, one that adopts ProtocolA and // one that does not. @interface Lovecraft @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 @end @interface Shoggoth_2 : Lovecraft_2 @end @interface Shoggoth_Explicit : Lovecraft @end @interface Shoggoth_2_Explicit : Lovecraft_2 @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) @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 - (void)methodA; // expected-note {{method 'methodA' declared here}} @end // NOT required @protocol Ex2ProtocolC - (void)methodB; - (void)methodA; @end @interface Ex2ClassA @end @implementation Ex2ClassA - (void)methodB {} - (void)methodA {} @end @interface Ex2ClassB : Ex2ClassA @end @implementation Ex2ClassB // expected-warning {{method 'methodA' in protocol 'Ex2ProtocolB' not implemented}} @end