aboutsummaryrefslogtreecommitdiff
path: root/test/SemaObjC/protocols-suppress-conformance.m
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaObjC/protocols-suppress-conformance.m')
-rw-r--r--test/SemaObjC/protocols-suppress-conformance.m207
1 files changed, 207 insertions, 0 deletions
diff --git a/test/SemaObjC/protocols-suppress-conformance.m b/test/SemaObjC/protocols-suppress-conformance.m
new file mode 100644
index 000000000000..299e44e8074e
--- /dev/null
+++ b/test/SemaObjC/protocols-suppress-conformance.m
@@ -0,0 +1,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;
+@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;
+@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 // no-warning
+- (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
+