diff --git a/clang/lib/Sema/Lookup.h b/clang/lib/Sema/Lookup.h index c5eecdac48e8..e761346c677c 100644 --- a/clang/lib/Sema/Lookup.h +++ b/clang/lib/Sema/Lookup.h @@ -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; }; } diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index f7f5fe3b4dde..c996d6e2b0b0 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/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(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 &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(*D)) - Results.MaybeAddResult(Result(ND, 0, InBaseClass), CurContext); - - // Visit transparent contexts inside this context. - if (DeclContext *InnerCtx = dyn_cast(*D)) { - if (InnerCtx->isTransparentContext()) - CollectMemberLookupResults(InnerCtx, CurContext, Visited, - Results, InBaseClass); - } - } - } - - // Traverse the contexts of inherited classes. - if (CXXRecordDecl *Record = dyn_cast(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(); - 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 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()) { // 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()) { diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index d7ee95896379..c6ab6a6b1980 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -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(*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(*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(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(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((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(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::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;