1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
// 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
|