nridge created this revision. Herald added subscribers: cfe-commits, usaxena95, kadircet, arphaman, jkorous, MaskRay, ilya-biryukov. Herald added a project: clang.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D76103 Files: clang-tools-extra/clangd/FindTarget.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 @@ -520,6 +520,14 @@ void test(unique_ptr<S<T>>& V) { V->fo^o(); } + )cpp", + + R"cpp(// Heuristic resolution of dependent enumerator + template <typename T> + struct Foo { + enum class E { [[A]], B }; + E e = E::A^; + }; )cpp"}; for (const char *Test : Tests) { Annotations T(Test); Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -57,6 +57,30 @@ return S; } +// This is similar to CXXRecordDecl::lookupDependentName(), but extended +// to handle certain other kinds of decls (currently, EnumDecl) as well. +std::vector<const NamedDecl *> +lookupDependentName(TagDecl *TD, DeclarationName Name, + llvm::function_ref<bool(const NamedDecl *ND)> Filter) { + if (TagDecl *Def = TD->getDefinition()) { + TD = Def; + } + + if (auto *RD = dyn_cast_or_null<CXXRecordDecl>(TD)) { + return RD->lookupDependentName(Name, Filter); + } + if (auto *ED = dyn_cast_or_null<EnumDecl>(TD)) { + std::vector<const NamedDecl *> Result; + for (const auto *Decl : ED->lookup(Name)) { + if (Filter(Decl)) { + Result.push_back(Decl); + } + } + return Result; + } + return {}; +} + // 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 @@ -76,22 +100,24 @@ bool IsNonstaticMember) { if (!T) return {}; - if (auto *ICNT = T->getAs<InjectedClassNameType>()) { - T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); + TagDecl *LookupInDecl = nullptr; + if (auto *ET = T->getAs<EnumType>()) { + LookupInDecl = ET->getDecl(); + } else { + if (auto *ICNT = T->getAs<InjectedClassNameType>()) { + T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); + } + auto *TST = T->getAs<TemplateSpecializationType>(); + if (!TST) + return {}; + const ClassTemplateDecl *TempD = dyn_cast_or_null<ClassTemplateDecl>( + TST->getTemplateName().getAsTemplateDecl()); + if (!TempD) + return {}; + LookupInDecl = TempD->getTemplatedDecl(); } - auto *TST = T->getAs<TemplateSpecializationType>(); - if (!TST) - return {}; - const ClassTemplateDecl *TD = dyn_cast_or_null<ClassTemplateDecl>( - 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) { + DeclarationName Name = NameFactory(LookupInDecl->getASTContext()); + return lookupDependentName(LookupInDecl, Name, [=](const NamedDecl *D) { return IsNonstaticMember ? D->isCXXInstanceMember() : !D->isCXXInstanceMember(); });
Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -520,6 +520,14 @@ void test(unique_ptr<S<T>>& V) { V->fo^o(); } + )cpp", + + R"cpp(// Heuristic resolution of dependent enumerator + template <typename T> + struct Foo { + enum class E { [[A]], B }; + E e = E::A^; + }; )cpp"}; for (const char *Test : Tests) { Annotations T(Test); Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -57,6 +57,30 @@ return S; } +// This is similar to CXXRecordDecl::lookupDependentName(), but extended +// to handle certain other kinds of decls (currently, EnumDecl) as well. +std::vector<const NamedDecl *> +lookupDependentName(TagDecl *TD, DeclarationName Name, + llvm::function_ref<bool(const NamedDecl *ND)> Filter) { + if (TagDecl *Def = TD->getDefinition()) { + TD = Def; + } + + if (auto *RD = dyn_cast_or_null<CXXRecordDecl>(TD)) { + return RD->lookupDependentName(Name, Filter); + } + if (auto *ED = dyn_cast_or_null<EnumDecl>(TD)) { + std::vector<const NamedDecl *> Result; + for (const auto *Decl : ED->lookup(Name)) { + if (Filter(Decl)) { + Result.push_back(Decl); + } + } + return Result; + } + return {}; +} + // 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 @@ -76,22 +100,24 @@ bool IsNonstaticMember) { if (!T) return {}; - if (auto *ICNT = T->getAs<InjectedClassNameType>()) { - T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); + TagDecl *LookupInDecl = nullptr; + if (auto *ET = T->getAs<EnumType>()) { + LookupInDecl = ET->getDecl(); + } else { + if (auto *ICNT = T->getAs<InjectedClassNameType>()) { + T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); + } + auto *TST = T->getAs<TemplateSpecializationType>(); + if (!TST) + return {}; + const ClassTemplateDecl *TempD = dyn_cast_or_null<ClassTemplateDecl>( + TST->getTemplateName().getAsTemplateDecl()); + if (!TempD) + return {}; + LookupInDecl = TempD->getTemplatedDecl(); } - auto *TST = T->getAs<TemplateSpecializationType>(); - if (!TST) - return {}; - const ClassTemplateDecl *TD = dyn_cast_or_null<ClassTemplateDecl>( - 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) { + DeclarationName Name = NameFactory(LookupInDecl->getASTContext()); + return lookupDependentName(LookupInDecl, Name, [=](const NamedDecl *D) { return IsNonstaticMember ? D->isCXXInstanceMember() : !D->isCXXInstanceMember(); });
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits