protocols-suppress-conformance.m 6.76 KB
// 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