summaryrefslogtreecommitdiff
path: root/clang/test/SemaObjC
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2019-01-09 22:31:37 +0000
committerAlex Lorenz <arphaman@gmail.com>2019-01-09 22:31:37 +0000
commit76b640b8ca82ea84d8f19e3015aa758ea19c2eae (patch)
treefa8d8560f9d9bc49987b5300055ad8db7d4bcaa8 /clang/test/SemaObjC
parente574d21647f668ae4fd34f292370b22455321c54 (diff)
[ObjC] Allow the use of implemented unavailable methods from within
the @implementation context In Objective-C, it's common for some frameworks to mark some methods like init as unavailable in the @interface to prohibit their usage. However, these frameworks then often implemented said method and refer to it in another method that acts as a factory for that object. The recent change to how messages to self are type checked in clang (r349841) introduced a regression which started to prohibit this pattern with an X is unavailable error. This commit addresses the aforementioned regression. rdar://47134898 Differential Revision: https://reviews.llvm.org/D56469
Diffstat (limited to 'clang/test/SemaObjC')
-rw-r--r--clang/test/SemaObjC/call-unavailable-init-in-self.m68
1 files changed, 68 insertions, 0 deletions
diff --git a/clang/test/SemaObjC/call-unavailable-init-in-self.m b/clang/test/SemaObjC/call-unavailable-init-in-self.m
new file mode 100644
index 00000000000..fa6f670cc99
--- /dev/null
+++ b/clang/test/SemaObjC/call-unavailable-init-in-self.m
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -x objective-c -verify -fobjc-arc %s
+
+@interface NSObject
+
++ (instancetype)new;
++ (instancetype)alloc;
+
+@end
+
+@interface Sub: NSObject
+
+- (instancetype)init __attribute__((unavailable)); // expected-note 4 {{'init' has been explicitly marked unavailable here}}
+
+- (void)notImplemented __attribute__((unavailable)); // expected-note {{'notImplemented' has been explicitly marked unavailable here}}
+
+@end
+
+@implementation Sub
+
++ (Sub *)create {
+ return [[self alloc] init];
+}
+
++ (Sub *)create2 {
+ return [self new];
+}
+
++ (Sub *)create3 {
+ return [Sub new];
+}
+
+- (instancetype) init {
+ return self;
+}
+
+- (void)reportUseOfUnimplemented {
+ [self notImplemented]; // expected-error {{'notImplemented' is unavailable}}
+}
+
+@end
+
+@interface SubClassContext: Sub
+@end
+
+@implementation SubClassContext
+
+- (void)subClassContext {
+ (void)[[Sub alloc] init]; // expected-error {{'init' is unavailable}}
+ (void)[Sub new]; // expected-error {{'new' is unavailable}}
+}
+
+@end
+
+void unrelatedContext() {
+ (void)[[Sub alloc] init]; // expected-error {{'init' is unavailable}}
+ (void)[Sub new]; // expected-error {{'new' is unavailable}}
+}
+
+@interface X @end
+
+@interface X (Foo)
+-(void)meth __attribute__((unavailable));
+@end
+
+@implementation X (Foo)
+-(void)meth {}
+-(void)call_it { [self meth]; }
+@end