]> granicus.if.org Git - clang/commitdiff
Tweak code-completion results by suppressing class template
authorDouglas Gregor <dgregor@apple.com>
Fri, 11 Dec 2009 17:31:05 +0000 (17:31 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 11 Dec 2009 17:31:05 +0000 (17:31 +0000)
specializations and class template partial specializations (they're
never named directly). Also, member access expressions only refer to
value declarations (fields, functions, enumerators, etc.) and
Objective-C property declarations; filter out everything else.

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

lib/Sema/SemaCodeComplete.cpp
test/CodeCompletion/member-access.cpp
test/Index/code-completion.cpp

index 63c8bdcc6c20bfd9c9b2c577422cad8ea1cda8d8..b1452b9152876804b0e126d34414194fb5cd3fb3 100644 (file)
@@ -364,11 +364,15 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
       (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend)))
     return;
 
-  // Class template (partial) specializations are never added as results
+  // Class template (partial) specializations are never added as results.
   if (isa<ClassTemplateSpecializationDecl>(CanonDecl) ||
       isa<ClassTemplatePartialSpecializationDecl>(CanonDecl))
     return;
   
+  // Using declarations themselves are never added as results.
+  if (isa<UsingDecl>(CanonDecl))
+    return;
+
   if (const IdentifierInfo *Id = R.Declaration->getIdentifier()) {
     // __va_list_tag is a freak of nature. Find it and skip it.
     if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
@@ -571,18 +575,19 @@ bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
   return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
 }
 
-/// \brief Brief determines whether the given declaration is a namespace or
-/// namespace alias.
+/// \brief Determines whether the given declaration is a type.
 bool ResultBuilder::IsType(NamedDecl *ND) const {
   return isa<TypeDecl>(ND);
 }
 
-/// \brief Since every declaration found within a class is a member that we
-/// care about, always returns true. This predicate exists mostly to 
-/// communicate to the result builder that we are performing a lookup for
-/// member access.
+/// \brief Determines which members of a class should be visible via
+/// "." or "->".  Only value declarations, nested name specifiers, and
+/// using declarations thereof should show up.
 bool ResultBuilder::IsMember(NamedDecl *ND) const {
-  return true;
+  if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
+    ND = Using->getTargetDecl();
+
+  return isa<ValueDecl>(ND) || isa<ObjCPropertyDecl>(ND);
 }
 
 // Find the next outer declaration context corresponding to this scope.
@@ -1479,6 +1484,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
 
       // We could have the start of a nested-name-specifier. Add those
       // results as well.
+      // FIXME: We should really walk base classes to produce
+      // nested-name-specifiers so that we produce more-precise results.
       Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
       CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
                            CurContext, Results);
index e445b4503aa301211b1b9f86bc4fbf794bf3fe23..6fefb64c705f896327eaf53870d712d7411366cd 100644 (file)
@@ -37,6 +37,6 @@ void test(const Proxy &p) {
   // CHECK-CC1: memfun1 : 0 : [#Base3::#]memfun1(<#double#>)
   // CHECK-CC1: memfun2 : 0 : [#Base3::#]memfun2(<#int#>)
   // CHECK-CC1: memfun3 : 0 : memfun3(<#int#>)
-  // CHECK-CC1: Base1 : 0 : Base1::
   // CHECK-CC1: memfun1 : 0 (Hidden) : Base2::memfun1(<#int#>)
+  // CHECK-CC1: Base1 : 3 : Base1::
   
index 44bd9d28932e52e09700cb494deebb9090c750f5..c286c82d048008aeb23eb930d7c2f3a4d4485477 100644 (file)
@@ -33,20 +33,19 @@ void test_overloaded() {
   overloaded(Z(), 0);
 }
 
-// CHECK-MEMBER: EnumDecl:{Informative X::}{TypedText E}
 // CHECK-MEMBER: FieldDecl:{TypedText member}
 // CHECK-MEMBER: FunctionDecl:{Informative Y::}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )}
 // CHECK-MEMBER: EnumConstantDecl:{Informative E::}{TypedText Val1}
 // CHECK-MEMBER: FunctionDecl:{Informative X::}{TypedText ~X}{LeftParen (}{RightParen )}
 // CHECK-MEMBER: FunctionDecl:{TypedText operator int}{LeftParen (}{RightParen )}
 // CHECK-MEMBER: FunctionDecl:{TypedText operator=}{LeftParen (}{Placeholder struct Z const &}{RightParen )}
-// CHECK-MEMBER: StructDecl:{TypedText X}{Text ::}
-// CHECK-MEMBER: StructDecl:{TypedText Y}{Text ::}
-// CHECK-MEMBER: StructDecl:{TypedText Z}{Text ::}
 // CHECK-MEMBER: FieldDecl:{Text X::}{TypedText member}
 // CHECK-MEMBER: FieldDecl:{Text Y::}{TypedText member}
 // CHECK-MEMBER: FunctionDecl:{Text X::}{TypedText operator=}{LeftParen (}{Placeholder struct X const &}{RightParen )}
 // CHECK-MEMBER: FunctionDecl:{Text Y::}{TypedText operator=}{LeftParen (}{Placeholder struct Y const &}{RightParen )}
+// CHECK-MEMBER: StructDecl:{TypedText X}{Text ::}
+// CHECK-MEMBER: StructDecl:{TypedText Y}{Text ::}
+// CHECK-MEMBER: StructDecl:{TypedText Z}{Text ::}
 
 // CHECK-OVERLOAD: NotImplemented:{Text overloaded}{LeftParen (}{Text struct Z z}{Comma , }{CurrentParameter int second}{RightParen )}
 // CHECK-OVERLOAD: NotImplemented:{Text overloaded}{LeftParen (}{Text int i}{Comma , }{CurrentParameter long second}{RightParen )}