diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-01-14 15:47:35 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-01-14 15:47:35 +0000 |
commit | 0cc8404f8cf320da140e560899e1560bce80fe8c (patch) | |
tree | 70cb5f8ce665a99a8c869cfca7947d6770f846ee /lib/Sema/SemaCodeComplete.cpp | |
parent | d346736dfe5ef584a2d0c9d27d217408ee394b9b (diff) |
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).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93428 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaCodeComplete.cpp')
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 121 |
1 files changed, 15 insertions, 106 deletions
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index f7f5fe3b4d..c996d6e2b0 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -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()) { |