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