1*0a6a1f1dSLionel Sambuc// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -verify %s -Wno-objc-root-class 2*0a6a1f1dSLionel Sambuc 3*0a6a1f1dSLionel Sambuc// Mark this protocol as requiring all of its methods and properties 4*0a6a1f1dSLionel Sambuc// to be explicitly implemented in the adopting class. 5*0a6a1f1dSLionel Sambuc__attribute__((objc_protocol_requires_explicit_implementation)) 6*0a6a1f1dSLionel Sambuc@protocol Protocol 7*0a6a1f1dSLionel Sambuc- (void) theBestOfTimes; // expected-note {{method 'theBestOfTimes' declared here}} 8*0a6a1f1dSLionel Sambuc@property (readonly) id theWorstOfTimes; // expected-note {{property declared here}} 9*0a6a1f1dSLionel Sambuc@end 10*0a6a1f1dSLionel Sambuc 11*0a6a1f1dSLionel Sambuc// In this example, ClassA adopts the protocol. We won't 12*0a6a1f1dSLionel Sambuc// provide the implementation here, but this protocol will 13*0a6a1f1dSLionel Sambuc// be adopted later by a subclass. 14*0a6a1f1dSLionel Sambuc@interface ClassA <Protocol> 15*0a6a1f1dSLionel Sambuc- (void) theBestOfTimes; 16*0a6a1f1dSLionel Sambuc@property (readonly) id theWorstOfTimes; // expected-note {{property declared here}} 17*0a6a1f1dSLionel Sambuc@end 18*0a6a1f1dSLionel Sambuc 19*0a6a1f1dSLionel Sambuc// This class subclasses ClassA (which also adopts 'Protocol'). 20*0a6a1f1dSLionel Sambuc@interface ClassB : ClassA <Protocol> 21*0a6a1f1dSLionel Sambuc@end 22*0a6a1f1dSLionel Sambuc 23*0a6a1f1dSLionel Sambuc@implementation ClassB // expected-warning {{property 'theWorstOfTimes' requires method 'theWorstOfTimes' to be defined - use @synthesize, @dynamic or provide a method implementation in this class implementation}} 24*0a6a1f1dSLionel Sambuc@end 25*0a6a1f1dSLionel Sambuc 26*0a6a1f1dSLionel Sambuc@interface ClassB_Good : ClassA <Protocol> 27*0a6a1f1dSLionel Sambuc@end 28*0a6a1f1dSLionel Sambuc 29*0a6a1f1dSLionel Sambuc@implementation ClassB_Good // no-warning 30*0a6a1f1dSLionel Sambuc- (void) theBestOfTimes {} 31*0a6a1f1dSLionel Sambuc@dynamic theWorstOfTimes; 32*0a6a1f1dSLionel Sambuc@end 33*0a6a1f1dSLionel Sambuc 34*0a6a1f1dSLionel Sambuc@interface ClassB_AlsoGood : ClassA <Protocol> 35*0a6a1f1dSLionel Sambuc@property (readonly) id theWorstOfTimes; // expected-warning {{auto property synthesis will not synthesize property 'theWorstOfTimes'; it will be implemented by its superclass}} 36*0a6a1f1dSLionel Sambuc@end 37*0a6a1f1dSLionel Sambuc 38*0a6a1f1dSLionel Sambuc// Default synthesis acts as if @dynamic 39*0a6a1f1dSLionel Sambuc// had been written for 'theWorstOfTimes' because 40*0a6a1f1dSLionel Sambuc// it is declared in ClassA. This is okay, since 41*0a6a1f1dSLionel Sambuc// the author of ClassB_AlsoGood needs explicitly 42*0a6a1f1dSLionel Sambuc// write @property in the @interface. 43*0a6a1f1dSLionel Sambuc@implementation ClassB_AlsoGood // expected-note {{detected while default synthesizing properties in class implementation}} 44*0a6a1f1dSLionel Sambuc- (void) theBestOfTimes {} 45*0a6a1f1dSLionel Sambuc@end 46*0a6a1f1dSLionel Sambuc 47*0a6a1f1dSLionel Sambuc// Test that inherited protocols do not get the explicit conformance requirement. 48*0a6a1f1dSLionel Sambuc@protocol Inherited 49*0a6a1f1dSLionel Sambuc- (void) fairIsFoul; 50*0a6a1f1dSLionel Sambuc@end 51*0a6a1f1dSLionel Sambuc 52*0a6a1f1dSLionel Sambuc__attribute__((objc_protocol_requires_explicit_implementation)) 53*0a6a1f1dSLionel Sambuc@protocol Derived <Inherited> 54*0a6a1f1dSLionel Sambuc- (void) foulIsFair; // expected-note {{method 'foulIsFair' declared here}} 55*0a6a1f1dSLionel Sambuc@end 56*0a6a1f1dSLionel Sambuc 57*0a6a1f1dSLionel Sambuc@interface ClassC <Inherited> 58*0a6a1f1dSLionel Sambuc@end 59*0a6a1f1dSLionel Sambuc 60*0a6a1f1dSLionel Sambuc@interface ClassD : ClassC <Derived> 61*0a6a1f1dSLionel Sambuc@end 62*0a6a1f1dSLionel Sambuc 63*0a6a1f1dSLionel Sambuc@implementation ClassD // expected-warning {{method 'foulIsFair' in protocol 'Derived' not implemented}} 64*0a6a1f1dSLionel Sambuc@end 65*0a6a1f1dSLionel Sambuc 66*0a6a1f1dSLionel Sambuc// Test that the attribute is used correctly. 67*0a6a1f1dSLionel Sambuc__attribute__((objc_protocol_requires_explicit_implementation(1+2))) // expected-error {{attribute takes no arguments}} 68*0a6a1f1dSLionel Sambuc@protocol AnotherProtocol @end 69*0a6a1f1dSLionel Sambuc 70*0a6a1f1dSLionel Sambuc// Cannot put the attribute on classes or other non-protocol declarations. 71*0a6a1f1dSLionel Sambuc__attribute__((objc_protocol_requires_explicit_implementation)) // expected-error {{attribute only applies to Objective-C protocols}} 72*0a6a1f1dSLionel Sambuc@interface AnotherClass @end 73*0a6a1f1dSLionel Sambuc 74*0a6a1f1dSLionel Sambuc__attribute__((objc_protocol_requires_explicit_implementation)) // expected-error {{attribute only applies to Objective-C protocols}} 75*0a6a1f1dSLionel Sambucint x; 76*0a6a1f1dSLionel Sambuc 77*0a6a1f1dSLionel Sambuc// Test that inherited protocols with the attribute 78*0a6a1f1dSLionel Sambuc// are treated properly. 79*0a6a1f1dSLionel Sambuc__attribute__((objc_protocol_requires_explicit_implementation)) 80*0a6a1f1dSLionel Sambuc@protocol ProtocolA 81*0a6a1f1dSLionel Sambuc@required 82*0a6a1f1dSLionel Sambuc- (void)rlyeh; // expected-note 2 {{method 'rlyeh' declared here}} 83*0a6a1f1dSLionel Sambuc- (void)innsmouth; // expected-note 2 {{method 'innsmouth' declared here}} 84*0a6a1f1dSLionel Sambuc@end 85*0a6a1f1dSLionel Sambuc 86*0a6a1f1dSLionel Sambuc@protocol ProtocolB <ProtocolA> 87*0a6a1f1dSLionel Sambuc@required 88*0a6a1f1dSLionel Sambuc- (void)dunwich; 89*0a6a1f1dSLionel Sambuc- (void)innsmouth; // expected-note {{method 'innsmouth' declared here}} 90*0a6a1f1dSLionel Sambuc@end 91*0a6a1f1dSLionel Sambuc 92*0a6a1f1dSLionel Sambuc__attribute__((objc_protocol_requires_explicit_implementation)) 93*0a6a1f1dSLionel Sambuc@protocol ProtocolB_Explicit <ProtocolA> 94*0a6a1f1dSLionel Sambuc@required 95*0a6a1f1dSLionel Sambuc- (void)dunwich; 96*0a6a1f1dSLionel Sambuc- (void)innsmouth; // expected-note 2 {{method 'innsmouth' declared here}} 97*0a6a1f1dSLionel Sambuc@end 98*0a6a1f1dSLionel Sambuc 99*0a6a1f1dSLionel Sambuc@protocol ProtocolC 100*0a6a1f1dSLionel Sambuc@required 101*0a6a1f1dSLionel Sambuc- (void)rlyeh; 102*0a6a1f1dSLionel Sambuc- (void)innsmouth; 103*0a6a1f1dSLionel Sambuc- (void)dunwich; 104*0a6a1f1dSLionel Sambuc@end 105*0a6a1f1dSLionel Sambuc 106*0a6a1f1dSLionel Sambuc@interface MyObject <ProtocolC> @end 107*0a6a1f1dSLionel Sambuc 108*0a6a1f1dSLionel Sambuc// Provide two variants of a base class, one that adopts ProtocolA and 109*0a6a1f1dSLionel Sambuc// one that does not. 110*0a6a1f1dSLionel Sambuc@interface Lovecraft <ProtocolA> @end 111*0a6a1f1dSLionel Sambuc@interface Lovecraft_2 @end 112*0a6a1f1dSLionel Sambuc 113*0a6a1f1dSLionel Sambuc// Provide two variants of a subclass that conform to ProtocolB. One 114*0a6a1f1dSLionel Sambuc// subclasses from a class that conforms to ProtocolA, the other that 115*0a6a1f1dSLionel Sambuc// does not. 116*0a6a1f1dSLionel Sambuc// 117*0a6a1f1dSLionel Sambuc// From those, provide two variants that conformat to ProtocolB_Explicit 118*0a6a1f1dSLionel Sambuc// instead. 119*0a6a1f1dSLionel Sambuc@interface Shoggoth : Lovecraft <ProtocolB> @end 120*0a6a1f1dSLionel Sambuc@interface Shoggoth_2 : Lovecraft_2 <ProtocolB> @end 121*0a6a1f1dSLionel Sambuc@interface Shoggoth_Explicit : Lovecraft <ProtocolB_Explicit> @end 122*0a6a1f1dSLionel Sambuc@interface Shoggoth_2_Explicit : Lovecraft_2 <ProtocolB_Explicit> @end 123*0a6a1f1dSLionel Sambuc 124*0a6a1f1dSLionel Sambuc@implementation MyObject 125*0a6a1f1dSLionel Sambuc- (void)innsmouth {} 126*0a6a1f1dSLionel Sambuc- (void)rlyeh {} 127*0a6a1f1dSLionel Sambuc- (void)dunwich {} 128*0a6a1f1dSLionel Sambuc@end 129*0a6a1f1dSLionel Sambuc 130*0a6a1f1dSLionel Sambuc@implementation Lovecraft 131*0a6a1f1dSLionel Sambuc- (void)innsmouth {} 132*0a6a1f1dSLionel Sambuc- (void)rlyeh {} 133*0a6a1f1dSLionel Sambuc@end 134*0a6a1f1dSLionel Sambuc 135*0a6a1f1dSLionel Sambuc@implementation Shoggoth 136*0a6a1f1dSLionel Sambuc- (void)dunwich {} 137*0a6a1f1dSLionel Sambuc@end 138*0a6a1f1dSLionel Sambuc 139*0a6a1f1dSLionel Sambuc@implementation Shoggoth_2 // expected-warning {{method 'innsmouth' in protocol 'ProtocolB' not implemented}}\ 140*0a6a1f1dSLionel Sambuc // expected-warning {{method 'rlyeh' in protocol 'ProtocolA' not implemented}}\ 141*0a6a1f1dSLionel Sambuc // expected-warning {{'innsmouth' in protocol 'ProtocolA' not implemented}} 142*0a6a1f1dSLionel Sambuc- (void)dunwich {} 143*0a6a1f1dSLionel Sambuc@end 144*0a6a1f1dSLionel Sambuc 145*0a6a1f1dSLionel Sambuc@implementation Shoggoth_Explicit // expected-warning {{method 'innsmouth' in protocol 'ProtocolB_Explicit' not implemented}} 146*0a6a1f1dSLionel Sambuc- (void)dunwich {} 147*0a6a1f1dSLionel Sambuc@end 148*0a6a1f1dSLionel Sambuc 149*0a6a1f1dSLionel Sambuc@implementation Shoggoth_2_Explicit // expected-warning {{method 'innsmouth' in protocol 'ProtocolB_Explicit' not implemented}}\ 150*0a6a1f1dSLionel Sambuc // expected-warning {{method 'rlyeh' in protocol 'ProtocolA' not implemented}}\ 151*0a6a1f1dSLionel Sambuc // expected-warning {{method 'innsmouth' in protocol 'ProtocolA' not implemented}} 152*0a6a1f1dSLionel Sambuc- (void)dunwich {} 153*0a6a1f1dSLionel Sambuc@end 154*0a6a1f1dSLionel Sambuc 155*0a6a1f1dSLionel Sambuc// Categories adopting a protocol with explicit conformance need to implement that protocol. 156*0a6a1f1dSLionel Sambuc@interface Parent 157*0a6a1f1dSLionel Sambuc- (void) theBestOfTimes; 158*0a6a1f1dSLionel Sambuc@property (readonly) id theWorstOfTimes; 159*0a6a1f1dSLionel Sambuc@end 160*0a6a1f1dSLionel Sambuc 161*0a6a1f1dSLionel Sambuc@interface Derived : Parent 162*0a6a1f1dSLionel Sambuc@end 163*0a6a1f1dSLionel Sambuc 164*0a6a1f1dSLionel Sambuc@interface Derived (MyCat) <Protocol> 165*0a6a1f1dSLionel Sambuc@end 166*0a6a1f1dSLionel Sambuc 167*0a6a1f1dSLionel Sambuc@implementation Derived (MyCat) // expected-warning {{method 'theBestOfTimes' in protocol 'Protocol' not implemented}} 168*0a6a1f1dSLionel Sambuc@end 169*0a6a1f1dSLionel Sambuc 170*0a6a1f1dSLionel Sambuc__attribute__((objc_protocol_requires_explicit_implementation)) // expected-error{{attribute 'objc_protocol_requires_explicit_implementation' can only be applied to @protocol definitions, not forward declarations}} 171*0a6a1f1dSLionel Sambuc@protocol NotDefined; 172*0a6a1f1dSLionel Sambuc 173*0a6a1f1dSLionel Sambuc// Another complete hierarchy. 174*0a6a1f1dSLionel Sambuc __attribute__((objc_protocol_requires_explicit_implementation)) 175*0a6a1f1dSLionel Sambuc@protocol Ex2FooBar 176*0a6a1f1dSLionel Sambuc- (void)methodA; 177*0a6a1f1dSLionel Sambuc@end 178*0a6a1f1dSLionel Sambuc 179*0a6a1f1dSLionel Sambuc __attribute__((objc_protocol_requires_explicit_implementation)) 180*0a6a1f1dSLionel Sambuc@protocol Ex2ProtocolA 181*0a6a1f1dSLionel Sambuc- (void)methodB; 182*0a6a1f1dSLionel Sambuc@end 183*0a6a1f1dSLionel Sambuc 184*0a6a1f1dSLionel Sambuc __attribute__((objc_protocol_requires_explicit_implementation)) 185*0a6a1f1dSLionel Sambuc@protocol Ex2ProtocolB <Ex2ProtocolA> 186*0a6a1f1dSLionel Sambuc- (void)methodA; // expected-note {{method 'methodA' declared here}} 187*0a6a1f1dSLionel Sambuc@end 188*0a6a1f1dSLionel Sambuc 189*0a6a1f1dSLionel Sambuc// NOT required 190*0a6a1f1dSLionel Sambuc@protocol Ex2ProtocolC <Ex2ProtocolA> 191*0a6a1f1dSLionel Sambuc- (void)methodB; 192*0a6a1f1dSLionel Sambuc- (void)methodA; 193*0a6a1f1dSLionel Sambuc@end 194*0a6a1f1dSLionel Sambuc 195*0a6a1f1dSLionel Sambuc@interface Ex2ClassA <Ex2ProtocolC, Ex2FooBar> 196*0a6a1f1dSLionel Sambuc@end 197*0a6a1f1dSLionel Sambuc@implementation Ex2ClassA 198*0a6a1f1dSLionel Sambuc- (void)methodB {} 199*0a6a1f1dSLionel Sambuc- (void)methodA {} 200*0a6a1f1dSLionel Sambuc@end 201*0a6a1f1dSLionel Sambuc 202*0a6a1f1dSLionel Sambuc@interface Ex2ClassB : Ex2ClassA <Ex2ProtocolB> 203*0a6a1f1dSLionel Sambuc@end 204*0a6a1f1dSLionel Sambuc 205*0a6a1f1dSLionel Sambuc@implementation Ex2ClassB // expected-warning {{method 'methodA' in protocol 'Ex2ProtocolB' not implemented}} 206*0a6a1f1dSLionel Sambuc@end 207*0a6a1f1dSLionel Sambuc 208