From: Nathan Ridge Date: Fri, 9 Jun 2023 06:39:28 +0000 (-0400) Subject: [clangd] Handle DependentNameType in HeuristicResolver::resolveTypeToRecordDecl() X-Git-Tag: upstream/17.0.6~4726 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7a709689bc1755a569864a97d93b96d22f988eb4;p=platform%2Fupstream%2Fllvm.git [clangd] Handle DependentNameType in HeuristicResolver::resolveTypeToRecordDecl() Fixes https://github.com/clangd/clangd/issues/1671 Differential Revision: https://reviews.llvm.org/D152645 --- diff --git a/clang-tools-extra/clangd/HeuristicResolver.cpp b/clang-tools-extra/clangd/HeuristicResolver.cpp index e91bd0e..7960ab9 100644 --- a/clang-tools-extra/clangd/HeuristicResolver.cpp +++ b/clang-tools-extra/clangd/HeuristicResolver.cpp @@ -10,6 +10,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/Type.h" namespace clang { namespace clangd { @@ -29,15 +30,39 @@ const auto TemplateFilter = [](const NamedDecl *D) { return isa(D); }; +namespace { + +const Type *resolveDeclsToType(const std::vector &Decls, + ASTContext &Ctx) { + if (Decls.size() != 1) // Names an overload set -- just bail. + return nullptr; + if (const auto *TD = dyn_cast(Decls[0])) { + return Ctx.getTypeDeclType(TD).getTypePtr(); + } + if (const auto *VD = dyn_cast(Decls[0])) { + return VD->getType().getTypePtrOrNull(); + } + return nullptr; +} + +} // namespace + // Helper function for HeuristicResolver::resolveDependentMember() // which takes a possibly-dependent type `T` and heuristically // resolves it to a CXXRecordDecl in which we can try name lookup. -CXXRecordDecl *resolveTypeToRecordDecl(const Type *T) { +CXXRecordDecl *HeuristicResolver::resolveTypeToRecordDecl(const Type *T) const { assert(T); // Unwrap type sugar such as type aliases. T = T->getCanonicalTypeInternal().getTypePtr(); + if (const auto *DNT = T->getAs()) { + T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx); + if (!T) + return nullptr; + T = T->getCanonicalTypeInternal().getTypePtr(); + } + if (const auto *RT = T->getAs()) return dyn_cast(RT->getDecl()); @@ -185,18 +210,6 @@ HeuristicResolver::resolveTemplateSpecializationType( DTST->getIdentifier(), TemplateFilter); } -const Type *resolveDeclsToType(const std::vector &Decls) { - if (Decls.size() != 1) // Names an overload set -- just bail. - return nullptr; - if (const auto *TD = dyn_cast(Decls[0])) { - return TD->getTypeForDecl(); - } - if (const auto *VD = dyn_cast(Decls[0])) { - return VD->getType().getTypePtrOrNull(); - } - return nullptr; -} - std::vector HeuristicResolver::resolveExprToDecls(const Expr *E) const { if (const auto *ME = dyn_cast(E)) { @@ -220,7 +233,7 @@ HeuristicResolver::resolveExprToDecls(const Expr *E) const { const Type *HeuristicResolver::resolveExprToType(const Expr *E) const { std::vector Decls = resolveExprToDecls(E); if (!Decls.empty()) - return resolveDeclsToType(Decls); + return resolveDeclsToType(Decls, Ctx); return E->getType().getTypePtr(); } @@ -239,9 +252,11 @@ const Type *HeuristicResolver::resolveNestedNameSpecifierToType( case NestedNameSpecifier::TypeSpecWithTemplate: return NNS->getAsType(); case NestedNameSpecifier::Identifier: { - return resolveDeclsToType(resolveDependentMember( - resolveNestedNameSpecifierToType(NNS->getPrefix()), - NNS->getAsIdentifier(), TypeFilter)); + return resolveDeclsToType( + resolveDependentMember( + resolveNestedNameSpecifierToType(NNS->getPrefix()), + NNS->getAsIdentifier(), TypeFilter), + Ctx); } default: break; diff --git a/clang-tools-extra/clangd/HeuristicResolver.h b/clang-tools-extra/clangd/HeuristicResolver.h index 2b66e4b..6e3a834 100644 --- a/clang-tools-extra/clangd/HeuristicResolver.h +++ b/clang-tools-extra/clangd/HeuristicResolver.h @@ -94,6 +94,11 @@ private: // `E`. const Type *resolveExprToType(const Expr *E) const; std::vector resolveExprToDecls(const Expr *E) const; + + // Helper function for HeuristicResolver::resolveDependentMember() + // which takes a possibly-dependent type `T` and heuristically + // resolves it to a CXXRecordDecl in which we can try name lookup. + CXXRecordDecl *resolveTypeToRecordDecl(const Type *T) const; }; } // namespace clangd diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index d54539b..8a69d4f 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -877,6 +877,22 @@ TEST_F(TargetDeclTest, DependentExprs) { } )cpp"; EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()"); + + Code = R"cpp( + template + struct Waldo { + void find(); + }; + template + struct MetaWaldo { + using Type = Waldo; + }; + template + void foo(typename MetaWaldo::Type w) { + w.[[find]](); + } + )cpp"; + EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()"); } TEST_F(TargetDeclTest, DependentTypes) {