aboutsummaryrefslogtreecommitdiff
path: root/test/SemaObjC
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaObjC')
-rw-r--r--test/SemaObjC/arc-peformselector.m12
-rw-r--r--test/SemaObjC/arc-repeated-weak.mm21
-rw-r--r--test/SemaObjC/arc-unavailable-for-weakref.m1
-rw-r--r--test/SemaObjC/arc.m32
-rw-r--r--test/SemaObjC/attr-deprecated.m12
-rw-r--r--test/SemaObjC/category-attribute.m23
-rw-r--r--test/SemaObjC/class-message-protocol-lookup.m27
-rw-r--r--test/SemaObjC/default-synthesize-3.m4
-rw-r--r--test/SemaObjC/objc-class-property.m9
-rw-r--r--test/SemaObjC/property-typecheck-1.m5
-rw-r--r--test/SemaObjC/special-dep-unavail-warning.m4
-rw-r--r--test/SemaObjC/unsafe-perform-selector.m127
-rw-r--r--test/SemaObjC/warn-deprecated-implementations.m11
13 files changed, 275 insertions, 13 deletions
diff --git a/test/SemaObjC/arc-peformselector.m b/test/SemaObjC/arc-peformselector.m
index dec09e33ed68..a7e5d3e8239e 100644
--- a/test/SemaObjC/arc-peformselector.m
+++ b/test/SemaObjC/arc-peformselector.m
@@ -8,6 +8,7 @@
- (id) init __attribute__((ns_returns_not_retained));
- (id)PlusZero;
- (id)PlusOne __attribute__((ns_returns_retained)); // expected-note {{method 'PlusOne' declared here}}
+- (id)self;
@end
@interface I : NSObject
@@ -17,6 +18,9 @@
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
+
+- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(double)delay inModes:(I *)modes;
+
@end
@implementation I
@@ -27,12 +31,20 @@
return [self performSelector : @selector(init)];
return [self performSelector : sel1]; // expected-warning {{performSelector may cause a leak because its selector is unknown}} \
// expected-note {{used here}}
+ return [self performSelector: (@selector(PlusZero))];
return [self performSelector : @selector(PlusZero)];
return [self performSelector : @selector(PlusOne)]; // expected-error {{performSelector names a selector which retains the object}}
+
+ // Avoid the unkown selector warning for more complicated performSelector
+ // variations because it produces too many false positives.
+ [self performSelector: sel1 withObject:0 afterDelay:0 inModes:0];
+
+ return [self performSelector: @selector(self)]; // No error, -self is not +1!
}
- (id)performSelector:(SEL)aSelector { return 0; }
- (id)performSelector:(SEL)aSelector withObject:(id)object { return 0; }
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 { return 0; }
+- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(double)delay inModes:(I *)modes { }
@end
diff --git a/test/SemaObjC/arc-repeated-weak.mm b/test/SemaObjC/arc-repeated-weak.mm
index 11161a0bf7fc..37b2123ec1c4 100644
--- a/test/SemaObjC/arc-repeated-weak.mm
+++ b/test/SemaObjC/arc-repeated-weak.mm
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s
@interface Test {
@public
@@ -445,8 +446,8 @@ void doubleLevelAccessIvar(Test *a, Test *b) {
@class NSString;
@interface NSBundle
+(NSBundle *)foo;
-@property (class) NSBundle *foo2;
-@property NSString *prop;
+@property (class, strong) NSBundle *foo2;
+@property (strong) NSString *prop;
@property(weak) NSString *weakProp;
@end
@@ -462,3 +463,19 @@ void foo() {
use(NSBundle.foo2.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(NSBundle2.foo2.weakProp); // expected-note{{also accessed here}}
}
+
+// This used to crash in the constructor of WeakObjectProfileTy when a
+// DeclRefExpr was passed that didn't reference a VarDecl.
+
+typedef INTF * INTFPtrTy;
+
+enum E {
+ e1
+};
+
+void foo1() {
+ INTFPtrTy tmp = (INTFPtrTy)e1;
+#if __has_feature(objc_arc)
+// expected-error@-2{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}}
+#endif
+}
diff --git a/test/SemaObjC/arc-unavailable-for-weakref.m b/test/SemaObjC/arc-unavailable-for-weakref.m
index 82748027435e..c59616819930 100644
--- a/test/SemaObjC/arc-unavailable-for-weakref.m
+++ b/test/SemaObjC/arc-unavailable-for-weakref.m
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-weak -verify -Wno-objc-root-class %s
// rdar://9693477
__attribute__((objc_arc_weak_reference_unavailable))
diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m
index f463bb03b075..e90d0a87e311 100644
--- a/test/SemaObjC/arc.m
+++ b/test/SemaObjC/arc.m
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -verify -Wno-objc-root-class -Wblock-capture-autoreleasing %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -verify -Wno-objc-root-class %s
+// RUN: not %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -Wno-objc-root-class -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
typedef unsigned long NSUInteger;
typedef const void * CFTypeRef;
@@ -809,9 +810,36 @@ int garf() {
TKAssertEqual(object, (id)nil);
}
-void block_capture_autoreleasing(A * __autoreleasing *a, A **b) { // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+void block_capture_autoreleasing(A * __autoreleasing *a,
+ A **b, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ A * _Nullable *c, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ A * _Nullable __autoreleasing *d,
+ A ** _Nullable e, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ A * __autoreleasing * _Nullable f,
+ id __autoreleasing *g,
+ id *h, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ id _Nullable *i, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ id _Nullable __autoreleasing *j,
+ id * _Nullable k, // expected-note {{declare the parameter __autoreleasing explicitly to suppress this warning}} expected-note {{declare the parameter __strong or capture a __block __strong variable to keep values alive across autorelease pools}}
+ id __autoreleasing * _Nullable l) {
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-11]]:37-[[@LINE-11]]:37}:" __autoreleasing "
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-11]]:47-[[@LINE-11]]:47}:" __autoreleasing"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-10]]:37-[[@LINE-10]]:37}:" __autoreleasing "
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-8]]:36-[[@LINE-8]]:36}:" __autoreleasing"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-8]]:46-[[@LINE-8]]:46}:" __autoreleasing"
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-7]]:36-[[@LINE-7]]:36}:" __autoreleasing"
^{
(void)*a;
(void)*b; // expected-warning {{block captures an autoreleasing out-parameter, which may result in use-after-free bugs}}
+ (void)*c; // expected-warning {{block captures an autoreleasing out-parameter, which may result in use-after-free bugs}}
+ (void)*d;
+ (void)*e; // expected-warning {{block captures an autoreleasing out-parameter, which may result in use-after-free bugs}}
+ (void)*f;
+ (void)*g;
+ (void)*h; // expected-warning {{block captures an autoreleasing out-parameter, which may result in use-after-free bugs}}
+ (void)*i; // expected-warning {{block captures an autoreleasing out-parameter, which may result in use-after-free bugs}}
+ (void)*j;
+ (void)*k; // expected-warning {{block captures an autoreleasing out-parameter, which may result in use-after-free bugs}}
+ (void)*l;
}();
}
diff --git a/test/SemaObjC/attr-deprecated.m b/test/SemaObjC/attr-deprecated.m
index 59087bdf1154..b0613851ddaa 100644
--- a/test/SemaObjC/attr-deprecated.m
+++ b/test/SemaObjC/attr-deprecated.m
@@ -83,8 +83,8 @@ int t5() {
}
-__attribute ((deprecated))
-@interface DEPRECATED { // expected-note 2 {{'DEPRECATED' has been explicitly marked deprecated here}}
+__attribute ((deprecated)) // expected-note 2 {{'DEPRECATED' has been explicitly marked deprecated here}}
+@interface DEPRECATED {
@public int ivar;
DEPRECATED *ivar2; // no warning.
}
@@ -121,9 +121,15 @@ void test(Test2 *foo) {
}
__attribute__((deprecated))
-@interface A(Blah) // expected-error{{attributes may not be specified on a category}}
+@interface A(Blah) // no warning
+- (A*)getA;
@end
+@implementation A(Blah) // Don't warn by default
+- (A*)getA {
+ return self;
+}
+@end
typedef struct {
int x;
diff --git a/test/SemaObjC/category-attribute.m b/test/SemaObjC/category-attribute.m
new file mode 100644
index 000000000000..7efe3df00ec8
--- /dev/null
+++ b/test/SemaObjC/category-attribute.m
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s
+// expected-no-diagnostics
+
+__attribute__ ((external_source_symbol(language= "Swift", defined_in="A")))
+@interface TestInterface
+@end
+// CHECK: ObjCInterfaceDecl {{.*}} TestInterface
+// CHECK-NEXT: ExternalSourceSymbolAttr
+
+__attribute__ ((external_source_symbol(language= "Swift", defined_in="B")))
+@interface TestInterface ()
+@end
+// CHECK: ObjCCategoryDecl
+// CHECK-NEXT: ObjCInterface
+// CHECK-NEXT: ExternalSourceSymbolAttr {{.*}} "Swift" "B"
+
+__attribute__ ((external_source_symbol(language= "Swift", defined_in="C")))
+@interface TestInterface (Category)
+@end
+// CHECK: ObjCCategoryDecl
+// CHECK-NEXT: ObjCInterface
+// CHECK-NEXT: ExternalSourceSymbolAttr {{.*}} "Swift" "C"
diff --git a/test/SemaObjC/class-message-protocol-lookup.m b/test/SemaObjC/class-message-protocol-lookup.m
index 37df7a641673..d9f954dc473d 100644
--- a/test/SemaObjC/class-message-protocol-lookup.m
+++ b/test/SemaObjC/class-message-protocol-lookup.m
@@ -32,3 +32,30 @@ int main ()
Class<Test2Protocol> c2 = [c2 alloc]; // ok
return 0;
}
+
+// rdar://22812517
+
+@protocol NSObject
+
+- (int)respondsToSelector:(SEL)aSelector;
+
+@end
+
+__attribute__((objc_root_class))
+@interface NSObject <NSObject>
+
+@end
+
+@protocol OtherProto
+
+- (void)otherInstanceMethod; // expected-note {{method 'otherInstanceMethod' declared here}}
+
+@end
+
+@protocol MyProto <NSObject, OtherProto>
+@end
+
+void allowInstanceMethodsFromRootProtocols(Class<MyProto> c) {
+ [c respondsToSelector: @selector(instanceMethod)]; // no warning
+ [c otherInstanceMethod]; // expected-warning {{instance method 'otherInstanceMethod' found instead of class method 'otherInstanceMethod'}}
+}
diff --git a/test/SemaObjC/default-synthesize-3.m b/test/SemaObjC/default-synthesize-3.m
index dce9edabb90d..fe2b35f61523 100644
--- a/test/SemaObjC/default-synthesize-3.m
+++ b/test/SemaObjC/default-synthesize-3.m
@@ -33,8 +33,8 @@ __attribute ((objc_requires_property_definitions)) // redundant, just for testi
- (id) DeepMustSynthProperty { return 0; }
@end
-__attribute ((objc_requires_property_definitions))
-@interface Deep(CAT) // expected-error {{attributes may not be specified on a category}}
+__attribute ((objc_requires_property_definitions)) // expected-error {{'objc_requires_property_definitions' attribute only applies to Objective-C interfaces}}
+@interface Deep(CAT)
@end
__attribute ((objc_requires_property_definitions)) // expected-error {{'objc_requires_property_definitions' attribute only applies to Objective-C interfaces}}
diff --git a/test/SemaObjC/objc-class-property.m b/test/SemaObjC/objc-class-property.m
index 56285976e194..f8d49112766d 100644
--- a/test/SemaObjC/objc-class-property.m
+++ b/test/SemaObjC/objc-class-property.m
@@ -21,6 +21,8 @@
@property (class) int c2; // expected-note {{property declared here}} \
// expected-note {{property declared here}}
@property (class) int x;
+@property (class, setter=customSet:) int customSetterProperty;
+@property (class, getter=customGet) int customGetterProperty;
@end
@implementation A // expected-warning {{class property 'c2' requires method 'c2' to be defined}} \
@@ -29,6 +31,8 @@
@dynamic (class) x; // refers to the class property
@synthesize z, c2; // expected-error {{@synthesize not allowed on a class property 'c2'}}
@dynamic c; // refers to the class property
+@dynamic customSetterProperty;
+@dynamic customGetterProperty;
@end
int test() {
@@ -37,6 +41,11 @@ int test() {
return a.x + A.c;
}
+void customSelectors() {
+ A.customSetterProperty = 1;
+ (void)A.customGetterProperty;
+}
+
void message_id(id me) {
[me y];
}
diff --git a/test/SemaObjC/property-typecheck-1.m b/test/SemaObjC/property-typecheck-1.m
index 5fb05c8bd384..85e8d4624be1 100644
--- a/test/SemaObjC/property-typecheck-1.m
+++ b/test/SemaObjC/property-typecheck-1.m
@@ -78,6 +78,11 @@ typedef void (F)(void);
- (NSMutableArray*) pieces; // expected-note 2 {{declared here}}
- (NSArray*) first;
+
+// Don't warn about setter-like methods for readonly properties.
+- (void)setFirst:(char)val;
+- (void)setPieces:(char)val;
+
@end
@interface Class2 {
diff --git a/test/SemaObjC/special-dep-unavail-warning.m b/test/SemaObjC/special-dep-unavail-warning.m
index 9e16b331c23c..b667c3c51c9d 100644
--- a/test/SemaObjC/special-dep-unavail-warning.m
+++ b/test/SemaObjC/special-dep-unavail-warning.m
@@ -44,8 +44,8 @@ void test(C *c) {
}
// rdar://10268422
-__attribute ((deprecated))
-@interface DEPRECATED // expected-note {{'DEPRECATED' has been explicitly marked deprecated here}}
+__attribute ((deprecated)) // expected-note {{'DEPRECATED' has been explicitly marked deprecated here}}
+@interface DEPRECATED
+(id)new;
@end
diff --git a/test/SemaObjC/unsafe-perform-selector.m b/test/SemaObjC/unsafe-perform-selector.m
new file mode 100644
index 000000000000..661ff363603f
--- /dev/null
+++ b/test/SemaObjC/unsafe-perform-selector.m
@@ -0,0 +1,127 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -verify %s
+// rdar://12056271
+
+@class Thread;
+
+__attribute__((objc_root_class))
+@interface NSObject
+
+- (id)performSelector:(SEL)sel;
+- (void)performSelectorInBackground:(SEL)sel withObject:(id)arg;
+- (void)performSelectorOnMainThread:(SEL)sel;
+
+- (void)performSelectorOnMainThread:(SEL)aSelector
+ onThread:(Thread *)thread
+ withObject:(id)arg
+ waitUntilDone:(int)wait
+ modes:(id *)array;
+
+@end
+
+typedef struct { int x; int y; int width; int height; } Rectangle;
+
+struct Struct { Rectangle r; };
+
+typedef union { int x; float f; } Union;
+
+@interface Base : NSObject
+
+- (struct Struct)returnsStruct2; // expected-note {{method 'returnsStruct2' that returns 'struct Struct' declared here}}
+- (Union)returnsId;
+
+@end
+
+@protocol IP
+
+- (Union)returnsUnion; // expected-note 2 {{method 'returnsUnion' that returns 'Union' declared here}}
+
+@end
+
+typedef __attribute__((__ext_vector_type__(3))) float float3;
+typedef int int4 __attribute__ ((vector_size (16)));
+
+@interface I : Base<IP>
+
+- (Rectangle)returnsStruct; // expected-note 4 {{method 'returnsStruct' that returns 'Rectangle' declared here}}
+- (id)returnsId; // shadows base 'returnsId'
+- (int)returnsInt;
+- (I *)returnPtr;
+- (float3)returnsExtVector; // expected-note {{method 'returnsExtVector' that returns 'float3' (vector of 3 'float' values) declared here}}
+- (int4)returnsVector; // expected-note {{method 'returnsVector' that returns 'int4' (vector of 4 'int' values) declared here}}
+
++ (Rectangle)returnsStructClass; // expected-note 2 {{method 'returnsStructClass' that returns 'Rectangle' declared here}}
++ (void)returnsUnion; // Not really
+
+@end
+
+void foo(I *i) {
+ [i performSelector: @selector(returnsStruct)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
+ [i performSelectorInBackground: @selector(returnsStruct) withObject:0]; // expected-warning {{'performSelectorInBackground:withObject:' is incompatible with selectors that return a struct type}}
+ [i performSelector: ((@selector(returnsUnion)))]; // expected-warning {{'performSelector:' is incompatible with selectors that return a union type}}
+ [i performSelectorOnMainThread: @selector(returnsStruct2)]; // expected-warning {{'performSelectorOnMainThread:' is incompatible with selectors that return a struct type}}
+ [I performSelector: (@selector(returnsStructClass))]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
+
+ [i performSelector: @selector(returnsId)];
+ [i performSelector: @selector(returnsInt)];
+ [i performSelector: @selector(returnsPtr)];
+ [I performSelector: @selector(returnsUnion)]; // No warning expected
+
+ id obj = i;
+ [obj performSelector: @selector(returnsId)];
+ [obj performSelector: @selector(returnsStruct)];
+}
+
+@interface SubClass: I
+
+@end
+
+@interface SubClass ()
+- (struct Struct)returnsSubStructExt; // expected-note {{method 'returnsSubStructExt' that returns 'struct Struct' declared here}} expected-note {{method 'returnsSubStructExt' declared here}}
+@end
+
+@implementation SubClass // expected-warning {{method definition for 'returnsSubStructExt' not found}}
+
+- (struct Struct)returnsSubStructImpl { // expected-note {{method 'returnsSubStructImpl' that returns 'struct Struct' declared here}}
+ struct Struct Result;
+ return Result;
+}
+
+- (void)checkPrivateCalls {
+ [self performSelector: @selector(returnsSubStructExt)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
+ [self performSelector: @selector(returnsSubStructImpl)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
+}
+
+- (void)checkSuperCalls {
+ [super performSelector: @selector(returnsStruct)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
+ [super performSelectorInBackground: @selector(returnsUnion) withObject: self]; // expected-warning {{'performSelectorInBackground:withObject:' is incompatible with selectors that return a union type}}
+ [super performSelector: @selector(returnsId)];
+}
+
++ (struct Struct)returnsSubStructClassImpl { // expected-note {{method 'returnsSubStructClassImpl' that returns 'struct Struct' declared here}}
+ struct Struct Result;
+ return Result;
+}
+
++ (void)checkClassPrivateCalls {
+ [self performSelector: @selector(returnsSubStructClassImpl)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
+}
+
++ (void)checkClassSuperCalls {
+ [super performSelector: @selector(returnsStructClass)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
+ [super performSelector: @selector(returnsUnion)]; // No warning expected
+}
+
+@end
+
+@implementation I (LongPerformSelectors)
+
+- (void)checkLongCallsFromCategory {
+ [self performSelectorOnMainThread: @selector(returnsStruct) onThread:0 withObject:self waitUntilDone:1 modes:0]; // expected-warning {{'performSelectorOnMainThread:onThread:withObject:waitUntilDone:modes:' is incompatible with selectors that return a struct type}}
+}
+
+- (void)checkVectorReturn {
+ [self performSelector: @selector(returnsExtVector)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a vector type}}
+ [self performSelector: @selector(returnsVector)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a vector type}}
+}
+
+@end
diff --git a/test/SemaObjC/warn-deprecated-implementations.m b/test/SemaObjC/warn-deprecated-implementations.m
index 6e208b5be795..0c341165b0f0 100644
--- a/test/SemaObjC/warn-deprecated-implementations.m
+++ b/test/SemaObjC/warn-deprecated-implementations.m
@@ -28,8 +28,8 @@
- (void) G {} // No warning, implementing its own deprecated method
@end
-__attribute__((deprecated))
-@interface CL // expected-note 2 {{class declared here}} // expected-note 2 {{'CL' has been explicitly marked deprecated here}}
+__attribute__((deprecated)) // expected-note 2 {{'CL' has been explicitly marked deprecated here}}
+@interface CL // expected-note 2 {{class declared here}}
@end
@implementation CL // expected-warning {{Implementing deprecated class}}
@@ -65,3 +65,10 @@ __attribute__((deprecated))
return (void *)0;
}
@end
+
+__attribute__((deprecated))
+@interface Test(DeprecatedCategory) // expected-note {{category declared here}}
+@end
+
+@implementation Test(DeprecatedCategory) // expected-warning {{Implementing deprecated category}}
+@end