Switch the remaining code completions over to LookupVisibleDecls,

after adding the ability to determine whether our lookup is a
base-class lookup. Eliminate CollectMemberLookupResults, since it is
no longer used (yay).

llvm-svn: 93428
This commit is contained in:
Douglas Gregor 2010-01-14 15:47:35 +00:00
parent 035ead209f
commit 09bbc651f4
3 changed files with 50 additions and 130 deletions

View File

@ -524,7 +524,11 @@ private:
///
/// \param Hiding a declaration that hides the declaration \p ND,
/// or NULL if no such declaration exists.
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding) = 0;
///
/// \param InBaseClass whether this declaration was found in base
/// class of the context we searched.
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
bool InBaseClass) = 0;
};
}

View File

@ -178,7 +178,11 @@ namespace {
/// \param CurContext the context in which this result will be named.
///
/// \param Hiding the declaration that hides the result.
void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding);
///
/// \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);
/// \brief Enter into a new scope.
void EnterNewScope();
@ -543,7 +547,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
}
void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
NamedDecl *Hiding) {
NamedDecl *Hiding, bool InBaseClass = false) {
assert(R.Kind == Result::RK_Declaration &&
"Only declaration results are supported");
@ -568,7 +572,11 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
// nested-name-specifier.
if (AsNestedNameSpecifier)
R.StartsNestedNameSpecifier = true;
else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
isa<CXXRecordDecl>(R.Declaration->getDeclContext()
->getLookupContext()))
R.QualifierIsInformative = true;
// If this result is supposed to have an informative qualifier, add one.
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
@ -703,112 +711,12 @@ namespace {
CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
: Results(Results), CurContext(CurContext) { }
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding) {
Results.AddResult(ND, CurContext, Hiding);
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) {
Results.AddResult(ND, CurContext, Hiding, InBaseClass);
}
};
}
/// \brief Collect the results of searching for members within the given
/// declaration context.
///
/// \param Ctx the declaration context from which we will gather results.
///
/// \param Visited the set of declaration contexts that have already been
/// visited. Declaration contexts will only be visited once.
///
/// \param Results the result set that will be extended with any results
/// found within this declaration context (and, for a C++ class, its bases).
///
/// \param InBaseClass whether we are in a base class.
static void CollectMemberLookupResults(DeclContext *Ctx,
DeclContext *CurContext,
llvm::SmallPtrSet<DeclContext *, 16> &Visited,
ResultBuilder &Results,
bool InBaseClass = false) {
// Make sure we don't visit the same context twice.
if (!Visited.insert(Ctx->getPrimaryContext()))
return;
// Enumerate all of the results in this context.
typedef CodeCompleteConsumer::Result Result;
Results.EnterNewScope();
for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx;
CurCtx = CurCtx->getNextContext()) {
for (DeclContext::decl_iterator D = CurCtx->decls_begin(),
DEnd = CurCtx->decls_end();
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
Results.MaybeAddResult(Result(ND, 0, InBaseClass), CurContext);
// Visit transparent contexts inside this context.
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) {
if (InnerCtx->isTransparentContext())
CollectMemberLookupResults(InnerCtx, CurContext, Visited,
Results, InBaseClass);
}
}
}
// Traverse the contexts of inherited classes.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(),
BEnd = Record->bases_end();
B != BEnd; ++B) {
QualType BaseType = B->getType();
// Don't look into dependent bases, because name lookup can't look
// there anyway.
if (BaseType->isDependentType())
continue;
const RecordType *Record = BaseType->getAs<RecordType>();
if (!Record)
continue;
// FIXME: It would be nice to be able to determine whether referencing
// a particular member would be ambiguous. For example, given
//
// struct A { int member; };
// struct B { int member; };
// struct C : A, B { };
//
// void f(C *c) { c->### }
// accessing 'member' would result in an ambiguity. However, code
// completion could be smart enough to qualify the member with the
// base class, e.g.,
//
// c->B::member
//
// or
//
// c->A::member
// Collect results from this base class (and its bases).
CollectMemberLookupResults(Record->getDecl(), CurContext, Visited,
Results, /*InBaseClass=*/true);
}
}
// FIXME: Look into base classes in Objective-C!
Results.ExitScope();
}
/// \brief Collect the results of searching for members within the given
/// declaration context.
///
/// \param Ctx the declaration context from which we will gather results.
///
/// \param Results the result set that will be extended with any results
/// found within this declaration context (and, for a C++ class, its bases).
static void CollectMemberLookupResults(DeclContext *Ctx,
DeclContext *CurContext,
ResultBuilder &Results) {
llvm::SmallPtrSet<DeclContext *, 16> Visited;
CollectMemberLookupResults(Ctx, CurContext, Visited, Results);
}
/// \brief Add type specifiers for the current language as keyword results.
static void AddTypeSpecifierResults(const LangOptions &LangOpts,
ResultBuilder &Results) {
@ -2086,7 +1994,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
if (const RecordType *Record = BaseType->getAs<RecordType>()) {
// Access to a C/C++ class, struct, or union.
Results.allowNestedNameSpecifiers();
CollectMemberLookupResults(Record->getDecl(), Record->getDecl(), Results);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer);
if (getLangOptions().CPlusPlus) {
if (!Results.empty()) {

View File

@ -1942,10 +1942,12 @@ NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
(*I)->getIdentifierNamespace() != IDNS)
continue;
// Functions and function templates overload rather than hide.
// FIXME: Look for hiding based on function signatures!
// Functions and function templates in the same scope overload
// rather than hide. FIXME: Look for hiding based on function
// signatures!
if ((*I)->isFunctionOrFunctionTemplate() &&
ND->isFunctionOrFunctionTemplate())
ND->isFunctionOrFunctionTemplate() &&
SM == ShadowMaps.rbegin())
continue;
// We've found a declaration that hides this one.
@ -1958,6 +1960,7 @@ NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
bool QualifiedNameLookup,
bool InBaseClass,
VisibleDeclConsumer &Consumer,
VisibleDeclsRecord &Visited) {
// Make sure we don't visit the same context twice.
@ -1972,14 +1975,14 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
if (Result.isAcceptableDecl(ND)) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND));
Consumer.FoundDecl(ND, Visited.checkHidden(ND), InBaseClass);
Visited.add(ND);
}
// Visit transparent contexts inside this context.
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) {
if (InnerCtx->isTransparentContext())
LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup,
LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup, InBaseClass,
Consumer, Visited);
}
}
@ -1991,7 +1994,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
DeclContext::udir_iterator I, E;
for (llvm::tie(I, E) = Ctx->getUsingDirectives(); I != E; ++I) {
LookupVisibleDecls((*I)->getNominatedNamespace(), Result,
QualifiedNameLookup, Consumer, Visited);
QualifiedNameLookup, InBaseClass, Consumer, Visited);
}
}
@ -2033,7 +2036,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Find results in this base class (and its bases).
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup,
Consumer, Visited);
true, Consumer, Visited);
}
}
@ -2043,34 +2046,37 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
for (ObjCCategoryDecl *Category = IFace->getCategoryList();
Category; Category = Category->getNextClassCategory()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(Category, Result, QualifiedNameLookup, Consumer,
Visited);
LookupVisibleDecls(Category, Result, QualifiedNameLookup, false,
Consumer, Visited);
}
// Traverse protocols.
for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
E = IFace->protocol_end(); I != E; ++I) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(*I, Result, QualifiedNameLookup, Consumer, Visited);
LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
Visited);
}
// Traverse the superclass.
if (IFace->getSuperClass()) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup,
Consumer, Visited);
true, Consumer, Visited);
}
} else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) {
for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(),
E = Protocol->protocol_end(); I != E; ++I) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(*I, Result, QualifiedNameLookup, Consumer, Visited);
LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
Visited);
}
} else if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Ctx)) {
for (ObjCCategoryDecl::protocol_iterator I = Category->protocol_begin(),
E = Category->protocol_end(); I != E; ++I) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(*I, Result, QualifiedNameLookup, Consumer, Visited);
LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
Visited);
}
}
}
@ -2089,7 +2095,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>((Decl *)((*D).get())))
if (Result.isAcceptableDecl(ND)) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND));
Consumer.FoundDecl(ND, Visited.checkHidden(ND), false);
Visited.add(ND);
}
}
@ -2112,7 +2118,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
Result.getNameLoc(), Sema::LookupMemberName);
ObjCInterfaceDecl *IFace = Method->getClassInterface();
LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
Consumer, Visited);
/*InBaseClass=*/false, Consumer, Visited);
}
// We've already performed all of the name lookup that we need
@ -2125,7 +2131,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
continue;
LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false,
Consumer, Visited);
/*InBaseClass=*/false, Consumer, Visited);
}
} else if (!S->getParent()) {
// Look into the translation unit scope. We walk through the translation
@ -2139,7 +2145,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
// in DeclContexts unless we have to" optimization), we can eliminate this.
Entity = Result.getSema().Context.getTranslationUnitDecl();
LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false,
Consumer, Visited);
/*InBaseClass=*/false, Consumer, Visited);
}
if (Entity) {
@ -2149,8 +2155,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity);
for (; UI != UEnd; ++UI)
LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()),
Result, /*QualifiedNameLookup=*/false, Consumer,
Visited);
Result, /*QualifiedNameLookup=*/false,
/*InBaseClass=*/false, Consumer, Visited);
}
// Lookup names in the parent scope.
@ -2185,8 +2191,8 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
VisibleDeclsRecord Visited;
ShadowContextRAII Shadow(Visited);
::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, Consumer,
Visited);
::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true,
/*InBaseClass=*/false, Consumer, Visited);
}
//----------------------------------------------------------------------------
@ -2209,7 +2215,7 @@ public:
explicit TypoCorrectionConsumer(IdentifierInfo *Typo)
: Typo(Typo->getName()) { }
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding);
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass);
typedef llvm::SmallVector<NamedDecl *, 4>::const_iterator iterator;
iterator begin() const { return BestResults.begin(); }
@ -2221,7 +2227,8 @@ public:
}
void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding) {
void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
bool InBaseClass) {
// Don't consider hidden names for typo correction.
if (Hiding)
return;