]> granicus.if.org Git - clang/commitdiff
objc rewriter - Add rewriter test for new instancetype
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 9 Sep 2011 20:35:22 +0000 (20:35 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 9 Sep 2011 20:35:22 +0000 (20:35 +0000)
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

lib/Rewrite/RewriteObjC.cpp
test/Rewriter/instancetype-test.mm [new file with mode: 0644]

index 83eba54c9db360d70b8452985c33c43f11331909..db59b518b731174afd3bc702bda4ddff1f2b50b2 100644 (file)
@@ -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 (file)
index 0000000..26f9ba2
--- /dev/null
@@ -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];
+}