aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-04-06 17:30:22 +0000
committerDouglas Gregor <dgregor@apple.com>2010-04-06 17:30:22 +0000
commit719770dcfcb3987e8a2377dcca97955301445eb5 (patch)
tree1da28b7f8b75c29bbc67187c5c4c96423db57f14
parent52d9ae3220c08fcbb80f213a364a88e4e0067242 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100535 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ExternalASTSource.h7
-rw-r--r--include/clang/Frontend/PCHReader.h3
-rw-r--r--lib/Frontend/PCHReader.cpp8
-rw-r--r--lib/Sema/SemaCodeComplete.cpp38
-rw-r--r--test/Index/Inputs/complete-pch.h10
-rw-r--r--test/Index/complete-pch.m26
6 files changed, 88 insertions, 4 deletions
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index b8d80bc897..79e44511d3 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -66,6 +66,13 @@ public:
/// 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.
///
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
index 73c1bf4cce..e324228e92 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Frontend/PCHReader.h
@@ -688,6 +688,9 @@ public:
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++]);
}
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index b96c04d0a8..41e06661fa 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -2843,6 +2843,14 @@ Selector PCHReader::DecodeSelector(unsigned ID) {
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++];
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index d29cab4ca1..ac56fab9e8 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -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 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
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 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
}
// 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))
diff --git a/test/Index/Inputs/complete-pch.h b/test/Index/Inputs/complete-pch.h
new file mode 100644
index 0000000000..ddf5253c13
--- /dev/null
+++ b/test/Index/Inputs/complete-pch.h
@@ -0,0 +1,10 @@
+@interface A
+- (int)instanceMethod1:(int)x;
++ (int)classMethod1:(double)d;
+@end
+
+@interface B
+- (int)instanceMethod2:(int)x;
++ (int)classMethod2:(float)f;
+@end
+
diff --git a/test/Index/complete-pch.m b/test/Index/complete-pch.m
new file mode 100644
index 0000000000..09192ae113
--- /dev/null
+++ b/test/Index/complete-pch.m
@@ -0,0 +1,26 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+@interface C
+- (int)instanceMethod3:(int)x;
++ (int)classMethod3:(float)f;
+@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}