[cfe-commits] r100535 - in /cfe/trunk: include/clang/AST/ExternalASTSource.h include/clang/Frontend/PCHReader.h lib/Frontend/PCHReader.cpp lib/Sema/SemaCodeComplete.cpp test/Index/Inputs/complete-pch.h test/Index/complete-pch.m

Douglas Gregor dgregor at apple.com
Tue Apr 6 10:30:22 PDT 2010


Author: dgregor
Date: Tue Apr  6 12:30:22 2010
New Revision: 100535

URL: http://llvm.org/viewvc/llvm-project?rev=100535&view=rev
Log:
Make code-completion for Objective-C message sends to "id" work in the
presence of precompiled headers by forcibly loading all of the
methods we know about from the PCH file before constructing our
code-completion list.

Added:
    cfe/trunk/test/Index/Inputs/complete-pch.h   (with props)
    cfe/trunk/test/Index/complete-pch.m
Modified:
    cfe/trunk/include/clang/AST/ExternalASTSource.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp

Modified: cfe/trunk/include/clang/AST/ExternalASTSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExternalASTSource.h?rev=100535&r1=100534&r2=100535&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExternalASTSource.h (original)
+++ cfe/trunk/include/clang/AST/ExternalASTSource.h Tue Apr  6 12:30:22 2010
@@ -66,6 +66,13 @@
   /// building a new declaration.
   virtual Decl *GetDecl(uint32_t ID) = 0;
 
+  /// \brief Resolve a selector ID into a selector.
+  virtual Selector GetSelector(uint32_t ID) = 0;
+
+  /// \brief Returns the number of selectors known to the external AST
+  /// source.
+  virtual uint32_t GetNumKnownSelectors() = 0;
+
   /// \brief Resolve the offset of a statement in the decl stream into a
   /// statement.
   ///

Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=100535&r1=100534&r2=100535&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Tue Apr  6 12:30:22 2010
@@ -688,6 +688,9 @@
 
   Selector DecodeSelector(unsigned Idx);
 
+  virtual Selector GetSelector(uint32_t ID);
+  virtual uint32_t GetNumKnownSelectors();
+
   Selector GetSelector(const RecordData &Record, unsigned &Idx) {
     return DecodeSelector(Record[Idx++]);
   }

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=100535&r1=100534&r2=100535&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Tue Apr  6 12:30:22 2010
@@ -2843,6 +2843,14 @@
   return SelectorsLoaded[Index];
 }
 
+Selector PCHReader::GetSelector(uint32_t ID) { 
+  return DecodeSelector(ID);
+}
+
+uint32_t PCHReader::GetNumKnownSelectors() {
+  return TotalNumSelectors + 1;
+}
+
 DeclarationName
 PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
   DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=100535&r1=100534&r2=100535&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Apr  6 12:30:22 2010
@@ -13,6 +13,7 @@
 #include "Sema.h"
 #include "Lookup.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/ExternalSemaSource.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/Lex/MacroInfo.h"
@@ -2977,13 +2978,26 @@
   else if (FName->isStr("id")) {
     // We're messaging "id" as a type; provide all class/factory methods.
 
-    // FIXME: Load the entire class method pool from the PCH file
+    // If we have an external source, load the entire class method
+    // pool from the PCH file.
+    if (ExternalSource) {
+      for (uint32_t I = 0, N = ExternalSource->GetNumKnownSelectors(); I != N;
+           ++I) {
+        Selector Sel = ExternalSource->GetSelector(I);
+        if (Sel.isNull() || FactoryMethodPool.count(Sel) || 
+            InstanceMethodPool.count(Sel))
+          continue;
+
+        ReadMethodPool(Sel, /*isInstance=*/false);
+      }
+    }
+
     for (llvm::DenseMap<Selector, ObjCMethodList>::iterator
            M = FactoryMethodPool.begin(),
            MEnd = FactoryMethodPool.end();
          M != MEnd;
          ++M) {
-      for (ObjCMethodList *MethList = &M->second; MethList; 
+      for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; 
            MethList = MethList->Next) {
         if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 
                                     NumSelIdents))
@@ -3056,13 +3070,29 @@
   }
   // Handle messages to "id".
   else if (ReceiverType->isObjCIdType()) {
-    // FIXME: Load the entire instance method pool from the PCH file
+    // We're messaging "id", so provide all instance methods we know
+    // about as code-completion results.
+
+    // If we have an external source, load the entire class method
+    // pool from the PCH file.
+    if (ExternalSource) {
+      for (uint32_t I = 0, N = ExternalSource->GetNumKnownSelectors(); I != N;
+           ++I) {
+        Selector Sel = ExternalSource->GetSelector(I);
+        if (Sel.isNull() || InstanceMethodPool.count(Sel) ||
+            FactoryMethodPool.count(Sel))
+          continue;
+
+        ReadMethodPool(Sel, /*isInstance=*/true);
+      }
+    }
+
     for (llvm::DenseMap<Selector, ObjCMethodList>::iterator
            M = InstanceMethodPool.begin(),
            MEnd = InstanceMethodPool.end();
          M != MEnd;
          ++M) {
-      for (ObjCMethodList *MethList = &M->second; MethList; 
+      for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; 
            MethList = MethList->Next) {
         if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 
                                     NumSelIdents))

Added: cfe/trunk/test/Index/Inputs/complete-pch.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/Inputs/complete-pch.h?rev=100535&view=auto
==============================================================================
--- cfe/trunk/test/Index/Inputs/complete-pch.h (added)
+++ cfe/trunk/test/Index/Inputs/complete-pch.h Tue Apr  6 12:30:22 2010
@@ -0,0 +1,10 @@
+ at interface A
+- (int)instanceMethod1:(int)x;
++ (int)classMethod1:(double)d;
+ at end
+
+ at interface B
+- (int)instanceMethod2:(int)x;
++ (int)classMethod2:(float)f;
+ at end
+

Propchange: cfe/trunk/test/Index/Inputs/complete-pch.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/Index/Inputs/complete-pch.h
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/Index/Inputs/complete-pch.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/Index/complete-pch.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-pch.m?rev=100535&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-pch.m (added)
+++ cfe/trunk/test/Index/complete-pch.m Tue Apr  6 12:30:22 2010
@@ -0,0 +1,26 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+ at interface C
+- (int)instanceMethod3:(int)x;
++ (int)classMethod3:(float)f;
+ at end
+
+void msg_id(id x) {
+  [id classMethod1:1.0];
+  [x instanceMethod1:5];
+}
+
+// Build the precompiled header
+// RUN: %clang -x objective-c-header -o %t.h.pch %S/Inputs/complete-pch.h
+
+// Run the actual tests
+// RUN: c-index-test -code-completion-at=%s:10:7 -include %t.h %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod1:}{Placeholder (double)d}
+// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod2:}{Placeholder (float)f}
+// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod3:}{Placeholder (float)f}
+
+// RUN: c-index-test -code-completion-at=%s:11:6 -include %t.h %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod1:}{Placeholder (int)x}
+// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod2:}{Placeholder (int)x}
+// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod3:}{Placeholder (int)x}





More information about the cfe-commits mailing list