From 98d763ad051f5eab89fa46167516fc8a84f471d0 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Wed, 8 Jul 2020 02:43:38 -0400 Subject: [PATCH] [clangd] Factor out some helper functions related to heuristic resolution in TargetFinder Summary: Two helpers are introduced: * Some of the logic previously in TargetFinder::Visit*() methods is factored out into resolveDependentExprToDecls(). * Some of the logic in getMembersReferencedViaDependentName() is factored out into resolveTypeToRecordDecl(). D82739 will build on this and use these functions in new ways. Reviewers: hokein Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D83371 --- clang-tools-extra/clangd/FindTarget.cpp | 81 ++++++++++++++++--------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index 1d09e8408c83..627f40c85436 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -58,6 +58,24 @@ nodeToString(const ast_type_traits::DynTypedNode &N) { return S; } +// Helper function for getMembersReferencedViaDependentName() +// which takes a dependent type `T` and heuristically +// resolves it to a CXXRecordDecl in which we can try name lookup. +CXXRecordDecl *resolveTypeToRecordDecl(const Type *T) { + assert(T); + if (const auto *ICNT = T->getAs()) { + T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); + } + const auto *TST = T->getAs(); + if (!TST) + return nullptr; + const ClassTemplateDecl *TD = dyn_cast_or_null( + TST->getTemplateName().getAsTemplateDecl()); + if (!TD) + return nullptr; + return TD->getTemplatedDecl(); +} + // Given a dependent type and a member name, heuristically resolve the // name to one or more declarations. // The current heuristic is simply to look up the name in the primary @@ -82,25 +100,17 @@ std::vector getMembersReferencedViaDependentName( ET->getDecl()->lookup(NameFactory(ET->getDecl()->getASTContext())); return {Result.begin(), Result.end()}; } - if (auto *ICNT = T->getAs()) { - T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); + if (auto *RD = resolveTypeToRecordDecl(T)) { + if (!RD->hasDefinition()) + return {}; + RD = RD->getDefinition(); + DeclarationName Name = NameFactory(RD->getASTContext()); + return RD->lookupDependentName(Name, [=](const NamedDecl *D) { + return IsNonstaticMember ? D->isCXXInstanceMember() + : !D->isCXXInstanceMember(); + }); } - auto *TST = T->getAs(); - if (!TST) - return {}; - const ClassTemplateDecl *TD = dyn_cast_or_null( - TST->getTemplateName().getAsTemplateDecl()); - if (!TD) - return {}; - CXXRecordDecl *RD = TD->getTemplatedDecl(); - if (!RD->hasDefinition()) - return {}; - RD = RD->getDefinition(); - DeclarationName Name = NameFactory(RD->getASTContext()); - return RD->lookupDependentName(Name, [=](const NamedDecl *D) { - return IsNonstaticMember ? D->isCXXInstanceMember() - : !D->isCXXInstanceMember(); - }); + return {}; } // Given the type T of a dependent expression that appears of the LHS of a "->", @@ -144,6 +154,28 @@ const Type *getPointeeType(const Type *T) { return FirstArg.getAsType().getTypePtrOrNull(); } +// Try to heuristically resolve a dependent expression `E` to one +// or more declarations that it likely references. +std::vector resolveDependentExprToDecls(const Expr *E) { + assert(E->isTypeDependent()); + if (const auto *ME = dyn_cast(E)) { + const Type *BaseType = ME->getBaseType().getTypePtrOrNull(); + if (ME->isArrow()) { + BaseType = getPointeeType(BaseType); + } + return getMembersReferencedViaDependentName( + BaseType, [ME](ASTContext &) { return ME->getMember(); }, + /*IsNonstaticMember=*/true); + } + if (const auto *RE = dyn_cast(E)) { + return getMembersReferencedViaDependentName( + RE->getQualifier()->getAsType(), + [RE](ASTContext &) { return RE->getDeclName(); }, + /*IsNonstaticMember=*/false); + } + return {}; +} + const NamedDecl *getTemplatePattern(const NamedDecl *D) { if (const CXXRecordDecl *CRD = dyn_cast(D)) { if (const auto *Result = CRD->getTemplateInstantiationPattern()) @@ -341,21 +373,12 @@ public: } void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) { - const Type *BaseType = E->getBaseType().getTypePtrOrNull(); - if (E->isArrow()) { - BaseType = getPointeeType(BaseType); - } - for (const NamedDecl *D : getMembersReferencedViaDependentName( - BaseType, [E](ASTContext &) { return E->getMember(); }, - /*IsNonstaticMember=*/true)) { + for (const NamedDecl *D : resolveDependentExprToDecls(E)) { Outer.add(D, Flags); } } void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { - for (const NamedDecl *D : getMembersReferencedViaDependentName( - E->getQualifier()->getAsType(), - [E](ASTContext &) { return E->getDeclName(); }, - /*IsNonstaticMember=*/false)) { + for (const NamedDecl *D : resolveDependentExprToDecls(E)) { Outer.add(D, Flags); } }