Attached test

Hi rsmith,

http://llvm-reviews.chandlerc.com/D622

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D622?vs=1764&id=1765#toc

Files:
  test/CodeCompletion/overridable-virtual.cpp
  lib/Sema/SemaCodeComplete.cpp
  include/clang/Sema/CodeCompleteConsumer.h
Index: test/CodeCompletion/overridable-virtual.cpp
===================================================================
--- test/CodeCompletion/overridable-virtual.cpp
+++ test/CodeCompletion/overridable-virtual.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -x c++ -fsyntax-only -std=c++11 -code-completion-at=%s:35:1 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+
+class A {
+public:
+    virtual ~A();
+
+    virtual void pureVirtual() = 0;
+    virtual void implementedVirtual() = 0;
+    virtual void virtualWithArgs(const int &a, float b);
+    virtual void virtualWithArgs(const float &a, bool b);
+    virtual void finalVirtual() const;
+};
+
+class B : public A {
+public:
+    virtual void finalVirtual() const final;
+    void virtualWithArgs(const int &a, float b);
+
+    virtual bool operator ==(const B &) const;
+};
+
+class C : public A
+{
+public:
+    void finalVirtual() const;
+    static void nonVirtualStatic();
+    void nonVirtual();
+    void virtualWithArgs(const int &a, float b);
+};
+
+class D : public B, public C
+{
+public:
+    void implementedVirtual();
+    
+// CHECK-CC1: operator== : [#bool#]operator==(<#const B &#>)[# const#]
+// CHECK-CC1: pureVirtual : [#void#]pureVirtual()
+// CHECK-CC1: virtualWithArgs : [#void#]virtualWithArgs(<#const float &a#>, <#bool b#>)
+// CHECK-CC1: virtualWithArgs : [#void#]virtualWithArgs(<#const int &a#>, <#float b#>)
+// CHECK-CC1-NOT: finalVirtual : [#void#]finalVirtual()[# const#]
+// CHECK-CC1-NOT: nonVirtual : [#void#]nonVirtual()
+// CHECK-CC1-NOT: nonVirtualStatic : [#void#]nonVirtualStatic()
+// CHECK-CC1-NOT: implementedVirtual : [#void#]implementedVirtual()
Index: lib/Sema/SemaCodeComplete.cpp
===================================================================
--- lib/Sema/SemaCodeComplete.cpp
+++ lib/Sema/SemaCodeComplete.cpp
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "clang/Sema/SemaInternal.h"
+#include "clang/AST/CXXInheritance.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
@@ -303,7 +304,7 @@
     /// \param InBaseClass whether the result was found in a base
     /// class of the searched context.
     void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
-                   bool InBaseClass);
+                   bool InBaseClass, bool WillOverridePureVirtual);
     
     /// \brief Add a new non-declaration result to this result set.
     void AddResult(Result R);
@@ -930,7 +931,8 @@
 }
 
 void ResultBuilder::AddResult(Result R, DeclContext *CurContext, 
-                              NamedDecl *Hiding, bool InBaseClass = false) {
+                              NamedDecl *Hiding, bool InBaseClass = false,
+                              bool WillOverridePureVirtual = false) {
   if (R.Kind != Result::RK_Declaration) {
     // For non-declaration results, just add the result.
     Results.push_back(R);
@@ -988,6 +990,9 @@
   // Adjust the priority if this result comes from a base class.
   if (InBaseClass)
     R.Priority += CCD_InBaseClass;
+  // Adjust the priority if this result overrides pure virtual method.
+  if (WillOverridePureVirtual)
+    R.Priority /= CCF_OverridePureVirtual;
   
   AdjustResultPriorityForDecl(R);
   
@@ -3215,6 +3220,9 @@
                             Results.data(),Results.size());
 }
 
+static void AddOverridableMethodsCompletions(Sema &SemaRef, Scope *S,
+                                             ResultBuilder &Results);
+
 void Sema::CodeCompleteOrdinaryName(Scope *S, 
                                     ParserCompletionContext CompletionContext) {
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
@@ -3227,7 +3235,6 @@
   // only allowed where we can have an expression.
   switch (CompletionContext) {
   case PCC_Namespace:
-  case PCC_Class:
   case PCC_ObjCInterface:
   case PCC_ObjCImplementation:
   case PCC_ObjCInstanceVariableList:
@@ -3238,6 +3245,13 @@
     Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
     break;
 
+  case PCC_Class: {
+    if (getLangOpts().CPlusPlus)
+      AddOverridableMethodsCompletions(*this, S, Results);
+    Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
+    break;
+  }
+
   case PCC_Statement:
   case PCC_ParenthesizedExpression:
   case PCC_Expression:
@@ -5407,6 +5421,75 @@
   return PreferredType;
 }
 
+static void AddOverridableMethodsCompletions(Sema &SemaRef, Scope *S,
+                                             ResultBuilder &Results)
+{
+  CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>((DeclContext *)S->getEntity());
+  CXXFinalOverriderMap Map;
+  Record->getFinalOverriders(Map);
+
+  // Discard base method if it's final overrider have 'final' attribute
+  llvm::SmallPtrSet<const CXXMethodDecl *, 8> DiscardedMethods;
+  for (CXXFinalOverriderMap::const_iterator I = Map.begin(),
+       E = Map.end(); I != E; ++I) {
+    if (isa<CXXDestructorDecl>(I->first))
+      continue;
+    const OverridingMethods& Methods = I->second;
+
+    for (OverridingMethods::const_iterator OI = Methods.begin(),
+                                        EndOI = Methods.end();
+         OI != EndOI; ++OI) {
+      const CXXMethodDecl *Method = OI->second.front().Method;
+      if (Method->getAttr<FinalAttr>()) {
+        DiscardedMethods.insert(I->first);
+        break;
+      }
+    }
+  }
+
+  // Discard final overrider if it's base method was discarded
+  llvm::SmallPtrSet<const CXXMethodDecl *, 8> DiscardedOverriders;
+  for (CXXFinalOverriderMap::const_iterator I = Map.begin(),
+       E = Map.end(); I != E; ++I) {
+    const OverridingMethods& Methods = I->second;
+    if (0 == DiscardedMethods.count(I->first))
+      continue;
+
+    for (OverridingMethods::const_iterator OI = Methods.begin(),
+                                        EndOI = Methods.end();
+         OI != EndOI; ++OI) {
+      const CXXMethodDecl *Method = OI->second.front().Method;
+      DiscardedOverriders.insert(Method);
+    }
+  }
+
+  // Finally, add completion for each base method that was not discarded
+  // and have no discarded final overriders.
+  for (CXXFinalOverriderMap::const_iterator I = Map.begin(),
+       E = Map.end(); I != E; ++I) {
+    if (isa<CXXDestructorDecl>(I->first) || DiscardedMethods.count(I->first))
+      continue;
+    const OverridingMethods& Methods = I->second;
+
+    CXXMethodDecl *MD = 0;
+    for (OverridingMethods::const_iterator OI = Methods.begin(),
+                                        EndOI = Methods.end();
+         !MD && OI != EndOI; ++OI) {
+      MD = OI->second.front().Method;
+      if (DiscardedOverriders.count(MD) || MD->getParent() == Record ||
+          MD != I->first)
+        MD = 0;
+    }
+    if (!MD)
+      continue;
+
+    bool Accessible = SemaRef.IsSimplyAccessible(MD, Record->getDeclContext());
+    ResultBuilder::Result Result2(MD, CCP_MemberDeclaration, 0,
+                                  false, Accessible);
+    Results.AddResult(Result2, Record, 0, true, MD->isPure());
+  }
+}
+
 static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, 
                                        ParsedType Receiver,
                                        IdentifierInfo **SelIdents,
Index: include/clang/Sema/CodeCompleteConsumer.h
===================================================================
--- include/clang/Sema/CodeCompleteConsumer.h
+++ include/clang/Sema/CodeCompleteConsumer.h
@@ -99,7 +99,10 @@
   /// \brief Divide by this factor when a code-completion result's type is
   /// similar to the type we expect (e.g., both arithmetic types, both
   /// Objective-C object pointer types).
-  CCF_SimilarTypeMatch = 2
+  CCF_SimilarTypeMatch = 2,
+  /// \brief Divide by this factor when a code-completion will override
+  /// pure virtual method rather than just virtual
+  CCF_OverridePureVirtual = 2
 };
 
 /// \brief A simplified classification of types used when determining
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to