From: Fariborz Jahanian Date: Fri, 9 Sep 2011 20:35:22 +0000 (+0000) Subject: objc rewriter - Add rewriter test for new instancetype X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=88914801a4d73e321c6f74f97df7d7b11c298bc6;p=clang 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 --- 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 alloc] methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}} + [[Subclass1 alloc] methodInProto2]; + + // instancetype on instance methods + Subclass1 *sc1proto1 = 0; + [[sc1proto1 self] methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}} + Subclass1 *sc1proto2 = 0; + [[sc1proto2 self] methodInProto2]; + + // Exact type checks + // Message sends to Class. + Subclass1 *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]; +}