nridge created this revision. Herald added subscribers: cfe-commits, usaxena95, kadircet, arphaman, jkorous. Herald added a project: clang. nridge requested review of this revision. Herald added subscribers: MaskRay, ilya-biryukov.
Fixes https://github.com/clangd/clangd/issues/307 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D86047 Files: clang-tools-extra/clangd/FindTarget.cpp clang-tools-extra/clangd/XRefs.cpp clang-tools-extra/clangd/unittests/XRefsTests.cpp
Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -734,7 +734,17 @@ Fo^o * getFoo() { return 0; } - )objc"}; + )objc", + R"cpp(// Member of dependent base + template <typename T> + struct Base { + void [[waldo]]() {} + }; + template <typename T> + struct Derived : Base<T> { + using Base<T>::w^aldo; + }; + )cpp"}; for (const char *Test : Tests) { Annotations T(Test); llvm::Optional<Range> WantDecl; Index: clang-tools-extra/clangd/XRefs.cpp =================================================================== --- clang-tools-extra/clangd/XRefs.cpp +++ clang-tools-extra/clangd/XRefs.cpp @@ -345,7 +345,7 @@ // Give the underlying decl if navigation is triggered on a non-renaming // alias. - if (llvm::isa<UsingDecl>(D)) { + if (llvm::isa<UsingDecl>(D) || llvm::isa<UnresolvedUsingValueDecl>(D)) { // FIXME: address more complicated cases. TargetDecl(... Underlying) gives // all overload candidates, we only want the targeted one if the cursor is // on an using-alias usage, workround it with getDeclAtPosition. Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -100,7 +100,7 @@ std::vector<const NamedDecl *> getMembersReferencedViaDependentName( const Type *T, llvm::function_ref<DeclarationName(ASTContext &)> NameFactory, - bool IsNonstaticMember) { + llvm::function_ref<bool(const NamedDecl *ND)> Filter) { if (!T) return {}; if (auto *ET = T->getAs<EnumType>()) { @@ -113,17 +113,24 @@ return {}; RD = RD->getDefinition(); DeclarationName Name = NameFactory(RD->getASTContext()); - return RD->lookupDependentName(Name, [=](const NamedDecl *D) { - return IsNonstaticMember ? D->isCXXInstanceMember() - : !D->isCXXInstanceMember(); - }); + return RD->lookupDependentName(Name, Filter); } return {}; } -// Given the type T of a dependent expression that appears of the LHS of a "->", -// heuristically find a corresponding pointee type in whose scope we could look -// up the name appearing on the RHS. +const auto NonStaticFilter = [](const NamedDecl *D) { + return D->isCXXInstanceMember(); +}; +const auto StaticFilter = [](const NamedDecl *D) { + return !D->isCXXInstanceMember(); +}; +const auto ValueFilter = [](const NamedDecl *D) { + return dyn_cast<ValueDecl>(D) != nullptr; +}; + +// Given the type T of a dependent expression that appears of the LHS of a +// "->", heuristically find a corresponding pointee type in whose scope we +// could look up the name appearing on the RHS. const Type *getPointeeType(const Type *T) { if (!T) return nullptr; @@ -141,7 +148,7 @@ [](ASTContext &Ctx) { return Ctx.DeclarationNames.getCXXOperatorName(OO_Arrow); }, - /*IsNonStaticMember=*/true); + NonStaticFilter); if (ArrowOps.empty()) return nullptr; @@ -187,13 +194,12 @@ } return getMembersReferencedViaDependentName( BaseType, [ME](ASTContext &) { return ME->getMember(); }, - /*IsNonstaticMember=*/true); + NonStaticFilter); } if (const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(E)) { return getMembersReferencedViaDependentName( RE->getQualifier()->getAsType(), - [RE](ASTContext &) { return RE->getDeclName(); }, - /*IsNonstaticMember=*/false); + [RE](ASTContext &) { return RE->getDeclName(); }, StaticFilter); } if (const auto *CE = dyn_cast<CallExpr>(E)) { const auto *CalleeType = resolveExprToType(CE->getCallee()); @@ -345,6 +351,15 @@ } else if (const auto *NAD = dyn_cast<NamespaceAliasDecl>(D)) { add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying); Flags |= Rel::Alias; // continue with the alias + } else if (const UnresolvedUsingValueDecl *UUVD = + dyn_cast<UnresolvedUsingValueDecl>(D)) { + for (const NamedDecl *Target : getMembersReferencedViaDependentName( + UUVD->getQualifier()->getAsType(), + [UUVD](ASTContext &) { return UUVD->getNameInfo().getName(); }, + ValueFilter)) { + add(Target, Flags | Rel::Underlying); + } + Flags |= Rel::Alias; // continue with the alias } else if (const UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) { // Include the using decl, but don't traverse it. This may end up // including *all* shadows, which we don't want.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits