]> granicus.if.org Git - clang/commitdiff
If an instance method messages is sending to an expression of type Class,
authorDouglas Gregor <dgregor@apple.com>
Mon, 8 Nov 2010 21:12:30 +0000 (21:12 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 8 Nov 2010 21:12:30 +0000 (21:12 +0000)
and we statically can compute a bound on the actual type (e.g.,
because it's a send to the the magic "class" instance method), code
complete as if we were performing a class message send to that class.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118443 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaCodeComplete.cpp
test/Index/complete-objc-message.m

index c245e38bb408bd7b5880f66b3a6f79652369499c..90b005ddc318431b9bf99fa27bf723c4cd776e99 100644 (file)
@@ -4695,6 +4695,21 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
                                             Context.getObjCInterfaceType(Super))
                                  : Context.getObjCIdType();
   
+  // If we're messaging an expression with type "id" or "Class", check
+  // whether we know something special about the receiver that allows
+  // us to assume a more-specific receiver type.
+  if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
+    if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
+      if (ReceiverType->isObjCClassType())
+        return CodeCompleteObjCClassMessage(S, 
+                       ParsedType::make(Context.getObjCInterfaceType(IFace)),
+                                            SelIdents, NumSelIdents,
+                                            AtArgumentExpression, Super);
+
+      ReceiverType = Context.getObjCObjectPointerType(
+                                          Context.getObjCInterfaceType(IFace));
+    }
+
   // Build the set of methods we can see.
   ResultBuilder Results(*this, CodeCompletionContext::CCC_Other);
   Results.EnterNewScope();
@@ -4712,14 +4727,6 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
   // others.
   if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
     Results.setPreferredSelector(CurMethod->getSelector());
-
-  // If we're messaging an expression with type "id" or "Class", check
-  // whether we know something special about the receiver that allows
-  // us to assume a more-specific receiver type.
-  if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
-    if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr))
-      ReceiverType = Context.getObjCObjectPointerType(
-                                          Context.getObjCInterfaceType(IFace));
   
   // Keep track of the selectors we've already added.
   VisitedSelectorSet Selectors;
index 161f544589dcaf8670113491890aecd4ba87b8fd..330e31fcd9e05dd73c704cd189b74f3c3dee5667 100644 (file)
@@ -150,6 +150,27 @@ void test_redundancy(C *c) {
   [c method2];
 };
 
+@protocol P
+- (Class)class;
+@end
+
+@interface A () <P>
+@end
+
+@interface A ()
++ (void)class_method3;
+@end
+
+@interface A (Cat)
++ (void)class_method4;
+@end
+
+@implementation A
+- (void)method5:(A*)a {
+  [[self class] class_method4];
+}
+@end
+
 // RUN: c-index-test -code-completion-at=%s:23:19 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: {TypedText categoryClassMethod}
 // CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)}{HorizontalSpace  }{TypedText withKeyword:}{Placeholder (int)}
@@ -256,6 +277,10 @@ void test_redundancy(C *c) {
 // CHECK-REDUNDANT-NOT: ObjCInstanceMethodDecl:{ResultType void}{TypedText method2}
 // CHECK-REDUNDANT: ObjCInstanceMethodDecl:{ResultType void}{TypedText method3} (35)
 
+// RUN: c-index-test -code-completion-at=%s:170:16 %s | FileCheck -check-prefix=CHECK-CLASS-RESULT %s
+// CHECK-CLASS-RESULT: ObjCClassMethodDecl:{ResultType void}{TypedText class_method3} (35)
+// CHECK-CLASS-RESULT: ObjCClassMethodDecl:{ResultType void}{TypedText class_method4} (35)
+
 // Test code completion with a missing opening bracket:
 // RUN: c-index-test -code-completion-at=%s:135:5 %s | FileCheck -check-prefix=CHECK-CCI %s
 // RUN: c-index-test -code-completion-at=%s:139:7 %s | FileCheck -check-prefix=CHECK-CC7 %s
@@ -268,3 +293,4 @@ void test_redundancy(C *c) {
 // RUN: c-index-test -code-completion-at=%s:141:14 %s | FileCheck -check-prefix=CHECK-CCC %s
 // RUN: c-index-test -code-completion-at=%s:141:23 %s | FileCheck -check-prefix=CHECK-CCD %s
 // RUN: c-index-test -code-completion-at=%s:141:30 %s | FileCheck -check-prefix=CHECK-CCE %s
+