diff options
author | Alex Lorenz <arphaman@gmail.com> | 2019-01-09 22:31:37 +0000 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2019-01-09 22:31:37 +0000 |
commit | 76b640b8ca82ea84d8f19e3015aa758ea19c2eae (patch) | |
tree | fa8d8560f9d9bc49987b5300055ad8db7d4bcaa8 /clang/test/SemaObjC | |
parent | e574d21647f668ae4fd34f292370b22455321c54 (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.m | 68 |
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 |