[cfe-commits] r112294 - in /cfe/trunk: lib/Sema/SemaCodeComplete.cpp test/Index/complete-super.cpp
Douglas Gregor
dgregor at apple.com
Fri Aug 27 14:18:54 PDT 2010
Author: dgregor
Date: Fri Aug 27 16:18:54 2010
New Revision: 112294
URL: http://llvm.org/viewvc/llvm-project?rev=112294&view=rev
Log:
Implement the "call super" code completion for C++. If the virtual
member function you're typing in overrides another virtual function,
this fills in a (qualified!) call to that virtual function to make
such delegation easy.
Added:
cfe/trunk/test/Index/complete-super.cpp
Modified:
cfe/trunk/lib/Sema/SemaCodeComplete.cpp
Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=112294&r1=112293&r2=112294&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Aug 27 16:18:54 2010
@@ -157,7 +157,7 @@
/// results.
bool includeCodePatterns() const {
return SemaRef.CodeCompleter &&
- SemaRef.CodeCompleter->includeCodePatterns();
+ SemaRef.CodeCompleter->includeCodePatterns();
}
/// \brief Set the filter used for code-completion results.
@@ -2383,10 +2383,84 @@
return CodeCompletionContext::CCC_Other;
}
+/// \brief If we're in a C++ virtual member function, add completion results
+/// that invoke the functions we override, since it's common to invoke the
+/// overridden function as well as adding new functionality.
+///
+/// \param S The semantic analysis object for which we are generating results.
+///
+/// \param InContext This context in which the nested-name-specifier preceding
+/// the code-completion point
+static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
+ ResultBuilder &Results) {
+ // Look through blocks.
+ DeclContext *CurContext = S.CurContext;
+ while (isa<BlockDecl>(CurContext))
+ CurContext = CurContext->getParent();
+
+
+ CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
+ if (!Method || !Method->isVirtual())
+ return;
+
+ // We need to have names for all of the parameters, if we're going to
+ // generate a forwarding call.
+ for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd;
+ ++P) {
+ if (!(*P)->getDeclName())
+ return;
+ }
+
+ for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
+ MEnd = Method->end_overridden_methods();
+ M != MEnd; ++M) {
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
+ if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
+ continue;
+
+ // If we need a nested-name-specifier, add one now.
+ if (!InContext) {
+ NestedNameSpecifier *NNS
+ = getRequiredQualification(S.Context, CurContext,
+ Overridden->getDeclContext());
+ if (NNS) {
+ std::string Str;
+ llvm::raw_string_ostream OS(Str);
+ NNS->print(OS, S.Context.PrintingPolicy);
+ Pattern->AddTextChunk(OS.str());
+ }
+ } else if (!InContext->Equals(Overridden->getDeclContext()))
+ continue;
+
+ Pattern->AddTypedTextChunk(Overridden->getNameAsString());
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ bool FirstParam = true;
+ for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd; ++P) {
+ if (FirstParam)
+ FirstParam = false;
+ else
+ Pattern->AddChunk(CodeCompletionString::CK_Comma);
+
+ Pattern->AddPlaceholderChunk((*P)->getIdentifier()->getName());
+ }
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(CodeCompletionResult(Pattern,
+ CCP_SuperCompletion,
+ CXCursor_CXXMethod));
+ Results.Ignore(Overridden);
+ }
+}
+
void Sema::CodeCompleteOrdinaryName(Scope *S,
ParserCompletionContext CompletionContext) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this);
+ Results.EnterNewScope();
// Determine how to filter results, e.g., so that the names of
// values (functions, enumerators, function templates, etc.) are
@@ -2417,6 +2491,9 @@
Results.setFilter(&ResultBuilder::IsOrdinaryName);
else
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
+
+ if (getLangOptions().CPlusPlus)
+ MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
break;
case PCC_RecoveryInFunction:
@@ -2435,7 +2512,6 @@
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals());
- Results.EnterNewScope();
AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Results.ExitScope();
@@ -3047,17 +3123,28 @@
return;
ResultBuilder Results(*this);
- CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
+ Results.EnterNewScope();
// The "template" keyword can follow "::" in the grammar, but only
// put it into the grammar if the nested-name-specifier is dependent.
NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
if (!Results.empty() && NNS->isDependent())
Results.AddResult("template");
+
+ // Add calls to overridden virtual functions, if there are any.
+ //
+ // FIXME: This isn't wonderful, because we don't know whether we're actually
+ // in a context that permits expressions. This is a general issue with
+ // qualified-id completions.
+ if (!EnteringContext)
+ MaybeAddOverrideCalls(*this, Ctx, Results);
+ Results.ExitScope();
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
+
HandleCodeCompleteResults(this, CodeCompleter,
- CodeCompletionContext::CCC_Other,
+ CodeCompletionContext::CCC_Name,
Results.data(),Results.size());
}
Added: cfe/trunk/test/Index/complete-super.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-super.cpp?rev=112294&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-super.cpp (added)
+++ cfe/trunk/test/Index/complete-super.cpp Fri Aug 27 16:18:54 2010
@@ -0,0 +1,33 @@
+// The run lines are below, because this test is line- and
+// column-number sensitive.
+
+struct A {
+ virtual void foo(int x, int y);
+ virtual void bar(double x);
+ virtual void bar(float x);
+};
+
+struct B : A {
+ void foo(int a, int b);
+ void bar(float real);
+};
+
+void B::foo(int a, int b) {
+ A::foo(a, b);
+}
+
+void B::bar(float real) {
+ A::bar(real);
+}
+
+// RUN: c-index-test -code-completion-at=%s:16:3 %s | FileCheck -check-prefix=CHECK-FOO-UNQUAL %s
+// CHECK-FOO-UNQUAL: CXXMethod:{Text A::}{TypedText foo}{LeftParen (}{Placeholder a}{Comma , }{Placeholder b}{RightParen )} (8)
+
+// RUN: c-index-test -code-completion-at=%s:20:3 %s | FileCheck -check-prefix=CHECK-BAR-UNQUAL %s
+// CHECK-BAR-UNQUAL: CXXMethod:{Text A::}{TypedText bar}{LeftParen (}{Placeholder real}{RightParen )} (8)
+// CHECK-BAR-UNQUAL: FunctionDecl:{ResultType void}{TypedText bar}{LeftParen (}{Placeholder float real}{RightParen )} (14)
+// CHECK-BAR-UNQUAL: FunctionDecl:{ResultType void}{Text A::}{TypedText bar}{LeftParen (}{Placeholder double x}{RightParen )} (16)
+
+// RUN: c-index-test -code-completion-at=%s:16:6 %s | FileCheck -check-prefix=CHECK-FOO-QUAL %s
+// CHECK-FOO-QUAL: CXXMethod:{TypedText foo}{LeftParen (}{Placeholder a}{Comma , }{Placeholder b}{RightParen )} (8)
+
More information about the cfe-commits
mailing list