forked from OSchip/llvm-project
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:
parent
035ead209f
commit
09bbc651f4
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue