summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-11-14 01:46:24 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-11-14 01:46:24 +0000
commitf3df1f7bf1bc23aa9f521107c69922e4a9503881 (patch)
tree19398f67050d8a08c1b27555b588dd2cdcdb9edc
parent00a301d56897719fb5674d6e24e054775b8bbfa7 (diff)
downloadbcm5719-llvm-f3df1f7bf1bc23aa9f521107c69922e4a9503881.tar.gz
bcm5719-llvm-f3df1f7bf1bc23aa9f521107c69922e4a9503881.zip
[completion] complete ObjC interface names in an expression
Objective-C interfaces can be used in a class property expression. rdar://26982192 llvm-svn: 318129
-rw-r--r--clang/lib/Frontend/ASTUnit.cpp6
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp11
-rw-r--r--clang/test/Index/complete-interfaces.m16
3 files changed, 30 insertions, 3 deletions
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 9eeec37a758..c69d3676de6 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -264,8 +264,12 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
// In Objective-C, you can only be a subclass of another Objective-C class
- if (isa<ObjCInterfaceDecl>(ND))
+ if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
+ // Objective-C interfaces can be used in a class property expression.
+ if (ID->getDefinition())
+ Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
+ }
// Deal with tag names.
if (isa<EnumDecl>(ND)) {
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 26004cf3c36..7ee24b114cc 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -1082,9 +1082,16 @@ bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
/// ordinary name lookup but is not a type name.
bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
- if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
+ if (isa<TypeDecl>(ND))
return false;
-
+ // Objective-C interfaces names are not filtered by this method because they
+ // can be used in a class property expression. We can still filter out
+ // @class declarations though.
+ if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
+ if (!ID->getDefinition())
+ return false;
+ }
+
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
diff --git a/clang/test/Index/complete-interfaces.m b/clang/test/Index/complete-interfaces.m
index 2f86c3d8f43..3e90407c78d 100644
--- a/clang/test/Index/complete-interfaces.m
+++ b/clang/test/Index/complete-interfaces.m
@@ -45,3 +45,19 @@
// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:11:12 %s | FileCheck -check-prefix=CHECK-CC2 %s
+
+
+void useClasses() {
+ int i = 0;
+ [Int3 message:1];
+}
+
+// RUN: c-index-test -code-completion-at=%s:51:11 %s | FileCheck -check-prefix=CHECK-USE %s
+// RUN: c-index-test -code-completion-at=%s:52:17 %s | FileCheck -check-prefix=CHECK-USE %s
+// CHECK-USE: ObjCInterfaceDecl:{TypedText Int2} (50)
+// CHECK-USE: ObjCInterfaceDecl:{TypedText Int3} (50)
+// CHECK-USE-NOT: Int1
+// CHECK-USE-NOT: Int4
+
+// Caching should work too:
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:51:11 %s | FileCheck -check-prefix=CHECK-USE %s
OpenPOWER on IntegriCloud