]> granicus.if.org Git - clang/commitdiff
When code completion walks the members of a protocol or interface,
authorDouglas Gregor <dgregor@apple.com>
Tue, 12 Jun 2012 13:44:08 +0000 (13:44 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 12 Jun 2012 13:44:08 +0000 (13:44 +0000)
make sure that we walk the definition. Fixes <rdar://problem/11427742>.

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

lib/Sema/SemaCodeComplete.cpp
test/Index/complete-method-decls.m
test/Index/complete-properties.m

index f8a9b4c2d1ce11c435c1aa1692c53c9325ba7c77..681190c0049b8c1d0a05ee4c4a7b61f9c0bca971 100644 (file)
@@ -3334,7 +3334,25 @@ void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
 /// property name.
 typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
 
-static void AddObjCProperties(ObjCContainerDecl *Container, 
+/// \brief Retrieve the container definition, if any?
+static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
+  if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
+    if (Interface->hasDefinition())
+      return Interface->getDefinition();
+    
+    return Interface;
+  }
+  
+  if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
+    if (Protocol->hasDefinition())
+      return Protocol->getDefinition();
+    
+    return Protocol;
+  }
+  return Container;
+}
+
+static void AddObjCProperties(ObjCContainerDecl *Container,
                               bool AllowCategories,
                               bool AllowNullaryMethods,
                               DeclContext *CurContext,
@@ -3342,6 +3360,9 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
                               ResultBuilder &Results) {
   typedef CodeCompletionResult Result;
 
+  // Retrieve the definition.
+  Container = getContainerDef(Container);
+  
   // Add properties in this container.
   for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
                                      PEnd = Container->prop_end();
@@ -3617,6 +3638,8 @@ void Sema::CodeCompleteCase(Scope *S) {
   // Code-complete the cases of a switch statement over an enumeration type
   // by providing the list of 
   EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
+  if (EnumDecl *Def = Enum->getDefinition())
+    Enum = Def;
   
   // Determine which enumerators we have already seen in the switch statement.
   // FIXME: Ideally, we would also be able to look *past* the code-completion
@@ -4695,6 +4718,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
                            ResultBuilder &Results,
                            bool InOriginalClass = true) {
   typedef CodeCompletionResult Result;
+  Container = getContainerDef(Container);
   for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
                                        MEnd = Container->meth_end();
        M != MEnd; ++M) {
@@ -5826,7 +5850,8 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
     return; 
 
   // Ignore any properties that have already been implemented.
-  for (DeclContext::decl_iterator D = Container->decls_begin(), 
+  Container = getContainerDef(Container);
+  for (DeclContext::decl_iterator D = Container->decls_begin(),
                                DEnd = Container->decls_end();
        D != DEnd; ++D)
     if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
@@ -5959,9 +5984,12 @@ static void FindImplementableMethods(ASTContext &Context,
                                      KnownMethodsMap &KnownMethods,
                                      bool InOriginalClass = true) {
   if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
-    // Recurse into protocols.
+    // Make sure we have a definition; that's what we'll walk.
     if (!IFace->hasDefinition())
       return;
+
+    IFace = IFace->getDefinition();
+    Container = IFace;
     
     const ObjCList<ObjCProtocolDecl> &Protocols
       = IFace->getReferencedProtocols();
@@ -6003,16 +6031,20 @@ static void FindImplementableMethods(ASTContext &Context,
   }
 
   if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
-    if (Protocol->hasDefinition()) {
-      // Recurse into protocols.
-      const ObjCList<ObjCProtocolDecl> &Protocols
-        = Protocol->getReferencedProtocols();
-      for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
-             E = Protocols.end(); 
-           I != E; ++I)
-        FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
-                                 KnownMethods, false);
-    }
+    // Make sure we have a definition; that's what we'll walk.
+    if (!Protocol->hasDefinition())
+      return;
+    Protocol = Protocol->getDefinition();
+    Container = Protocol;
+        
+    // Recurse into protocols.
+    const ObjCList<ObjCProtocolDecl> &Protocols
+      = Protocol->getReferencedProtocols();
+    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+           E = Protocols.end(); 
+         I != E; ++I)
+      FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
+                               KnownMethods, false);
   }
 
   // Add methods in this container. This operation occurs last because
index becb7de6eb8bc2743b4b92c722623ae00a248e61..ce48246370925cb01acd6f74e36ef8587b8d9e9c 100644 (file)
@@ -8,7 +8,7 @@
 - (int)getInt;
 - (id)getSelf;
 @end
-
+@protocol P1;
 @protocol P2<P1>
 + (id)alloc;
 @end
index ce1870e6511b52874bb5d88fe721125f4f6263c4..a4450563698eb362d3fa3d3356b17cc06f1986c7 100644 (file)
@@ -45,6 +45,17 @@ id test(I3 *i3) {
 @synthesize Prop2 = Prop2_;
 @end
 
+@protocol P1
+@property int Prop5;
+@end
+
+@class P1;
+
+@interface I5<P1>
+@end
+@implementation I5
+@synthesize Prop5;
+@end
 // RUN: c-index-test -code-completion-at=%s:20:13 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText Prop0}
 // CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText Prop1}
@@ -80,3 +91,6 @@ id test(I3 *i3) {
 // CHECK-CC7-NOT: ObjCIvarDecl:{ResultType id}{TypedText _Prop2}
 // CHECK-CC7: ObjCIvarDecl:{ResultType I4 *}{TypedText Prop1} (17)
 // CHECK-CC7: ObjCIvarDecl:{ResultType id}{TypedText Prop2_} (7)
+
+// RUN: c-index-test -code-completion-at=%s:57:13 -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC8 %s
+// CHECK-CC8: ObjCPropertyDecl:{ResultType int}{TypedText Prop5} (35)