diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -163,13 +163,12 @@ } // Forward declaration, needed as this function is mutually recursive -// with resolveDependentExprToDecls. -const Type *resolveDependentExprToType(const Expr *E); +// with resolveExprToDecls. +const Type *resolveExprToType(const Expr *E); -// Try to heuristically resolve a dependent expression `E` to one +// Try to heuristically resolve a possibly-dependent expression `E` to one // or more declarations that it likely references. -std::vector resolveDependentExprToDecls(const Expr *E) { - assert(E->isTypeDependent()); +std::vector resolveExprToDecls(const Expr *E) { if (const auto *ME = dyn_cast(E)) { const Type *BaseType = ME->getBaseType().getTypePtrOrNull(); if (ME->isArrow()) { @@ -183,7 +182,7 @@ // can get further by analyzing the depedent expression. Expr *Base = ME->isImplicitAccess() ? nullptr : ME->getBase(); if (Base && BT->getKind() == BuiltinType::Dependent) { - BaseType = resolveDependentExprToType(Base); + BaseType = resolveExprToType(Base); } } return getMembersReferencedViaDependentName( @@ -197,7 +196,7 @@ /*IsNonstaticMember=*/false); } if (const auto *CE = dyn_cast(E)) { - const auto *CalleeType = resolveDependentExprToType(CE->getCallee()); + const auto *CalleeType = resolveExprToType(CE->getCallee()); if (!CalleeType) return {}; if (const auto *FnTypePtr = CalleeType->getAs()) @@ -209,15 +208,16 @@ } } } - if (const auto *ME = dyn_cast(E)) { + if (const auto *ME = dyn_cast(E)) return {ME->getMemberDecl()}; - } + if (const auto *DRE = dyn_cast(E)) + return {DRE->getFoundDecl()}; return {}; } -// Try to heuristically resolve the type of a dependent expression `E`. -const Type *resolveDependentExprToType(const Expr *E) { - std::vector Decls = resolveDependentExprToDecls(E); +// Try to heuristically resolve the type of a possibly-dependent expression `E`. +const Type *resolveExprToType(const Expr *E) { + std::vector Decls = resolveExprToDecls(E); if (Decls.size() != 1) // Names an overload set -- just bail. return nullptr; if (const auto *TD = dyn_cast(Decls[0])) { @@ -426,12 +426,12 @@ } void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) { - for (const NamedDecl *D : resolveDependentExprToDecls(E)) { + for (const NamedDecl *D : resolveExprToDecls(E)) { Outer.add(D, Flags); } } void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { - for (const NamedDecl *D : resolveDependentExprToDecls(E)) { + for (const NamedDecl *D : resolveExprToDecls(E)) { Outer.add(D, Flags); } } diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -627,6 +627,20 @@ }; )cpp"; EXPECT_DECLS("CXXDependentScopeMemberExpr", "int aaaa"); + + Code = R"cpp( + class Foo { + public: + static Foo k(int); + template T convert() const; + }; + template + void test() { + Foo::k(T()).template [[convert]](); + } + )cpp"; + EXPECT_DECLS("CXXDependentScopeMemberExpr", + "template T convert() const"); } TEST_F(TargetDeclTest, ObjC) {