diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-09-09 20:35:22 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-09-09 20:35:22 +0000 |
commit | 88914801a4d73e321c6f74f97df7d7b11c298bc6 (patch) | |
tree | 1e6b4f67a8a3bcd41f02ba7de6886c258c27a3a3 | |
parent | 5c16d635ff67fd8f083a704b7c82607ed49a8ba2 (diff) |
objc rewriter - Add rewriter test for new instancetype
along with minor rewriter fix to handle that. This
test is still incomplete due to rewriter issues
unrelated to instancetype.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139403 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Rewrite/RewriteObjC.cpp | 4 | ||||
-rw-r--r-- | test/Rewriter/instancetype-test.mm | 73 |
2 files changed, 76 insertions, 1 deletions
diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp index 83eba54c9d..db59b518b7 100644 --- a/lib/Rewrite/RewriteObjC.cpp +++ b/lib/Rewrite/RewriteObjC.cpp @@ -465,6 +465,8 @@ namespace { const QualType *args, unsigned numArgs, bool variadic = false) { + if (result == Context->getObjCInstanceType()) + result = Context->getObjCIdType(); FunctionProtoType::ExtProtoInfo fpi; fpi.Variadic = variadic; return Context->getFunctionType(result, args, numArgs, fpi); @@ -970,7 +972,7 @@ void RewriteObjC::RewriteForwardClassDecl( void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { // When method is a synthesized one, such as a getter/setter there is // nothing to rewrite. - if (Method->isSynthesized()) + if (Method->isImplicit()) return; SourceLocation LocStart = Method->getLocStart(); SourceLocation LocEnd = Method->getLocEnd(); diff --git a/test/Rewriter/instancetype-test.mm b/test/Rewriter/instancetype-test.mm new file mode 100644 index 0000000000..26f9ba2590 --- /dev/null +++ b/test/Rewriter/instancetype-test.mm @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp + +void *sel_registerName(const char *); + +@interface Root ++ (instancetype)alloc; +- (instancetype)init; // expected-note{{overridden method is part of the 'init' method family}} +- (instancetype)self; +- (Class)class; + +@property (assign) Root *selfProp; +- (instancetype)selfProp; +@end + +@protocol Proto1 +@optional +- (instancetype)methodInProto1; +@end + +@protocol Proto2 +@optional +- (instancetype)methodInProto2; // expected-note{{overridden method returns an instance of its class type}} +- (instancetype)otherMethodInProto2; // expected-note{{overridden method returns an instance of its class type}} +@end + +@interface Subclass1 : Root +- (instancetype)initSubclass1; +- (void)methodOnSubclass1; ++ (instancetype)allocSubclass1; +@end + +@interface Subclass2 : Root +- (instancetype)initSubclass2; +- (void)methodOnSubclass2; +@end + +// Sanity check: the basic initialization pattern. +void test_instancetype_alloc_init_simple() { + Root *r1 = [[Root alloc] init]; + Subclass1 *sc1 = [[Subclass1 alloc] init]; +} + +// Test that message sends to instancetype methods have the right type. +void test_instancetype_narrow_method_search() { + // instancetype on class methods + Subclass1 *sc1 = [[Subclass1 alloc] initSubclass2]; // expected-warning{{'Subclass1' may not respond to 'initSubclass2'}} + Subclass2 *sc2 = [[Subclass2 alloc] initSubclass2]; // okay + + // instancetype on instance methods + [[[Subclass1 alloc] init] methodOnSubclass2]; // expected-warning{{'Subclass1' may not respond to 'methodOnSubclass2'}} + [[[Subclass2 alloc] init] methodOnSubclass2]; + + // instancetype on class methods using protocols + [[Subclass1<Proto1> alloc] methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}} + [[Subclass1<Proto2> alloc] methodInProto2]; + + // instancetype on instance methods + Subclass1<Proto1> *sc1proto1 = 0; + [[sc1proto1 self] methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}} + Subclass1<Proto2> *sc1proto2 = 0; + [[sc1proto2 self] methodInProto2]; + + // Exact type checks + // Message sends to Class. + Subclass1<Proto1> *sc1proto1_2 = [[[sc1proto1 class] alloc] init]; + + // Property access + [sc1proto1.self methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}} + [sc1proto2.self methodInProto2]; + + [sc1proto1.selfProp methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}} + [sc1proto2.selfProp methodInProto2]; +} |