[cfe-commits] r82476 - in /cfe/trunk: lib/Sema/SemaCodeComplete.cpp test/CodeCompletion/member-access.cpp
Douglas Gregor
dgregor at apple.com
Mon Sep 21 13:12:40 PDT 2009
Author: dgregor
Date: Mon Sep 21 15:12:40 2009
New Revision: 82476
URL: http://llvm.org/viewvc/llvm-project?rev=82476&view=rev
Log:
When providing a code-completion suggestion for a hidden name, include
a nested-name-specifier that describes how to refer to that name. For
example, given:
struct Base { int member; };
struct Derived : Base { int member; };
the code-completion result for a member access into "Derived" will
provide both "member" to refer to Derived::member (no qualification needed) and
"Base::member" to refer to Base::member (qualification included).
Modified:
cfe/trunk/lib/Sema/SemaCodeComplete.cpp
cfe/trunk/test/CodeCompletion/member-access.cpp
Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=82476&r1=82475&r2=82476&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Mon Sep 21 15:12:40 2009
@@ -86,7 +86,11 @@
/// \brief Add a new result to this result set (if it isn't already in one
/// of the shadow maps), or replace an existing result (for, e.g., a
/// redeclaration).
- void MaybeAddResult(Result R);
+ ///
+ /// \param R the result to add (if it is unique).
+ ///
+ /// \param R the context in which this result will be named.
+ void MaybeAddResult(Result R, DeclContext *CurContext = 0);
/// \brief Enter into a new scope.
void EnterNewScope();
@@ -133,14 +137,57 @@
if (HiddenCtx->isFunctionOrMethod())
return false;
- // If the hidden and visible declarations are in different name-lookup
- // contexts, then we can qualify the name of the hidden declaration.
- // FIXME: Optionally compute the string needed to refer to the hidden
- // name.
return HiddenCtx != Visible->getDeclContext()->getLookupContext();
}
-void ResultBuilder::MaybeAddResult(Result R) {
+/// \brief Compute the qualification required to get from the current context
+/// (\p CurContext) to the target context (\p TargetContext).
+///
+/// \param Context the AST context in which the qualification will be used.
+///
+/// \param CurContext the context where an entity is being named, which is
+/// typically based on the current scope.
+///
+/// \param TargetContext the context in which the named entity actually
+/// resides.
+///
+/// \returns a nested name specifier that refers into the target context, or
+/// NULL if no qualification is needed.
+static NestedNameSpecifier *
+getRequiredQualification(ASTContext &Context,
+ DeclContext *CurContext,
+ DeclContext *TargetContext) {
+ llvm::SmallVector<DeclContext *, 4> TargetParents;
+
+ for (DeclContext *CommonAncestor = TargetContext;
+ CommonAncestor && !CommonAncestor->Encloses(CurContext);
+ CommonAncestor = CommonAncestor->getLookupParent()) {
+ if (CommonAncestor->isTransparentContext() ||
+ CommonAncestor->isFunctionOrMethod())
+ continue;
+
+ TargetParents.push_back(CommonAncestor);
+ }
+
+ NestedNameSpecifier *Result = 0;
+ while (!TargetParents.empty()) {
+ DeclContext *Parent = TargetParents.back();
+ TargetParents.pop_back();
+
+ if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent))
+ Result = NestedNameSpecifier::Create(Context, Result, Namespace);
+ else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
+ Result = NestedNameSpecifier::Create(Context, Result,
+ false,
+ Context.getTypeDeclType(TD).getTypePtr());
+ else
+ assert(Parent->isTranslationUnit());
+ }
+
+ return Result;
+}
+
+void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
if (R.Kind != Result::RK_Declaration) {
// For non-declaration results, just add the result.
Results.push_back(R);
@@ -149,7 +196,8 @@
// Look through using declarations.
if (UsingDecl *Using = dyn_cast<UsingDecl>(R.Declaration))
- return MaybeAddResult(Result(Using->getTargetDecl(), R.Rank));
+ return MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier),
+ CurContext);
// Handle each declaration in an overload set separately.
if (OverloadedFunctionDecl *Ovl
@@ -157,7 +205,7 @@
for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
FEnd = Ovl->function_end();
F != FEnd; ++F)
- MaybeAddResult(Result(*F, R.Rank));
+ MaybeAddResult(Result(*F, R.Rank, R.Qualifier), CurContext);
return;
}
@@ -232,6 +280,11 @@
I->second.first)) {
// Note that this result was hidden.
R.Hidden = true;
+
+ if (!R.Qualifier)
+ R.Qualifier = getRequiredQualification(SemaRef.Context,
+ CurContext,
+ R.Declaration->getDeclContext());
} else {
// This result was hidden and cannot be found; don't bother adding
// it.
@@ -329,53 +382,6 @@
return 0;
}
-/// \brief Compute the qualification required to get from the current context
-/// (\p CurContext) to the target context (\p TargetContext).
-///
-/// \param Context the AST context in which the qualification will be used.
-///
-/// \param CurContext the context where an entity is being named, which is
-/// typically based on the current scope.
-///
-/// \param TargetContext the context in which the named entity actually
-/// resides.
-///
-/// \returns a nested name specifier that refers into the target context, or
-/// NULL if no qualification is needed.
-static NestedNameSpecifier *
-getRequiredQualification(ASTContext &Context,
- DeclContext *CurContext,
- DeclContext *TargetContext) {
- llvm::SmallVector<DeclContext *, 4> TargetParents;
-
- for (DeclContext *CommonAncestor = TargetContext;
- CommonAncestor && !CommonAncestor->Encloses(CurContext);
- CommonAncestor = CommonAncestor->getLookupParent()) {
- if (CommonAncestor->isTransparentContext() ||
- CommonAncestor->isFunctionOrMethod())
- continue;
-
- TargetParents.push_back(CommonAncestor);
- }
-
- NestedNameSpecifier *Result = 0;
- while (!TargetParents.empty()) {
- DeclContext *Parent = TargetParents.back();
- TargetParents.pop_back();
-
- if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent))
- Result = NestedNameSpecifier::Create(Context, Result, Namespace);
- else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
- Result = NestedNameSpecifier::Create(Context, Result,
- false,
- Context.getTypeDeclType(TD).getTypePtr());
- else
- assert(Parent->isTranslationUnit());
- }
-
- return Result;
-}
-
/// \brief Collect the results of searching for members within the given
/// declaration context.
///
@@ -395,7 +401,8 @@
/// names within this declaration context.
static unsigned CollectMemberLookupResults(DeclContext *Ctx,
unsigned InitialRank,
- llvm::SmallPtrSet<DeclContext *, 16> &Visited,
+ DeclContext *CurContext,
+ llvm::SmallPtrSet<DeclContext *, 16> &Visited,
ResultBuilder &Results) {
// Make sure we don't visit the same context twice.
if (!Visited.insert(Ctx->getPrimaryContext()))
@@ -409,7 +416,8 @@
DEnd = CurCtx->decls_end();
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
- Results.MaybeAddResult(CodeCompleteConsumer::Result(ND, InitialRank));
+ Results.MaybeAddResult(CodeCompleteConsumer::Result(ND, InitialRank),
+ CurContext);
}
}
@@ -452,6 +460,7 @@
NextRank = std::max(NextRank,
CollectMemberLookupResults(Record->getDecl(),
InitialRank + 1,
+ CurContext,
Visited,
Results));
}
@@ -479,9 +488,11 @@
/// names within this declaration context.
static unsigned CollectMemberLookupResults(DeclContext *Ctx,
unsigned InitialRank,
+ DeclContext *CurContext,
ResultBuilder &Results) {
llvm::SmallPtrSet<DeclContext *, 16> Visited;
- return CollectMemberLookupResults(Ctx, InitialRank, Visited, Results);
+ return CollectMemberLookupResults(Ctx, InitialRank, CurContext, Visited,
+ Results);
}
/// \brief Collect the results of searching for declarations within the given
@@ -492,10 +503,13 @@
/// \param InitialRank the initial rank given to results in this scope.
/// Larger rank values will be used for results found in parent scopes.
///
+/// \param CurContext the context from which lookup results will be found.
+///
/// \param Results the builder object that will receive each result.
static unsigned CollectLookupResults(Scope *S,
TranslationUnitDecl *TranslationUnit,
unsigned InitialRank,
+ DeclContext *CurContext,
ResultBuilder &Results) {
if (!S)
return InitialRank;
@@ -517,7 +531,8 @@
if (Ctx->isFunctionOrMethod())
continue;
- NextRank = CollectMemberLookupResults(Ctx, NextRank + 1, Results);
+ NextRank = CollectMemberLookupResults(Ctx, NextRank + 1, CurContext,
+ Results);
}
} else if (!S->getParent()) {
// Look into the translation unit scope. We walk through the translation
@@ -531,13 +546,14 @@
// in DeclContexts unless we have to" optimization), we can eliminate the
// TranslationUnit parameter entirely.
NextRank = CollectMemberLookupResults(TranslationUnit, NextRank + 1,
- Results);
+ CurContext, Results);
} else {
// Walk through the declarations in this Scope.
for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>((Decl *)((*D).get())))
- Results.MaybeAddResult(CodeCompleteConsumer::Result(ND, NextRank));
+ Results.MaybeAddResult(CodeCompleteConsumer::Result(ND, NextRank),
+ CurContext);
}
NextRank = NextRank + 1;
@@ -545,7 +561,7 @@
// Lookup names in the parent scope.
NextRank = CollectLookupResults(S->getParent(), TranslationUnit, NextRank,
- Results);
+ CurContext, Results);
Results.ExitScope();
return NextRank;
@@ -882,7 +898,8 @@
unsigned NextRank = 0;
if (const RecordType *Record = BaseType->getAs<RecordType>()) {
- NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank, Results);
+ NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank,
+ Record->getDecl(), Results);
if (getLangOptions().CPlusPlus) {
if (!Results.empty()) {
@@ -906,7 +923,7 @@
// results as well.
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
- Results);
+ CurContext, Results);
}
// Hand off the results found for code completion.
@@ -944,14 +961,14 @@
ResultBuilder Results(*this, Filter);
unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
- 0, Results);
+ 0, CurContext, Results);
if (getLangOptions().CPlusPlus) {
// We could have the start of a nested-name-specifier. Add those
// results as well.
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
- Results);
+ CurContext, Results);
}
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
@@ -1045,7 +1062,7 @@
return;
ResultBuilder Results(*this);
- unsigned NextRank = CollectMemberLookupResults(Ctx, 0, Results);
+ unsigned NextRank = CollectMemberLookupResults(Ctx, 0, Ctx, Results);
// The "template" keyword can follow "::" in the grammar, but only
// put it into the grammar if the nested-name-specifier is dependent.
@@ -1068,7 +1085,8 @@
// After "using", we can see anything that would start a
// nested-name-specifier.
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, Results);
+ CollectLookupResults(S, Context.getTranslationUnitDecl(), 0,
+ CurContext, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1080,7 +1098,8 @@
// After "using namespace", we expect to see a namespace name or namespace
// alias.
ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, Results);
+ CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext,
+ Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1109,7 +1128,8 @@
for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
NS != NSEnd; ++NS)
- Results.MaybeAddResult(CodeCompleteConsumer::Result(NS->second, 0));
+ Results.MaybeAddResult(CodeCompleteConsumer::Result(NS->second, 0),
+ CurContext);
}
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
@@ -1121,7 +1141,8 @@
// After "namespace", we expect to see a namespace or alias.
ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, Results);
+ CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext,
+ Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
@@ -1140,7 +1161,7 @@
// Add any type names visible from the current scope
unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(),
- 0, Results);
+ 0, CurContext, Results);
// Add any type specifiers
AddTypeSpecifierResults(getLangOptions(), 0, Results);
@@ -1148,7 +1169,7 @@
// Add any nested-name-specifiers
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank + 1,
- Results);
+ CurContext, Results);
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
Modified: cfe/trunk/test/CodeCompletion/member-access.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/member-access.cpp?rev=82476&r1=82475&r2=82476&view=diff
==============================================================================
--- cfe/trunk/test/CodeCompletion/member-access.cpp (original)
+++ cfe/trunk/test/CodeCompletion/member-access.cpp Mon Sep 21 15:12:40 2009
@@ -38,5 +38,5 @@
// CHECK-CC1: member1 : 2
// CHECK-CC1: member2 : 2
// CHECK-CC1: member3 : 2
- // CHECK-CC1: memfun1 : 2 (Hidden)
+ // CHECK-CC1: memfun1 : 2 (Hidden) : Base2::memfun1(<#int#>)
p->
\ No newline at end of file
More information about the cfe-commits
mailing list