Author: Kadir Cetinkaya Date: 2020-01-28T11:22:02+01:00 New Revision: a31a61dafeaa9110687110fc127ea6f7c91dd3e6
URL: https://github.com/llvm/llvm-project/commit/a31a61dafeaa9110687110fc127ea6f7c91dd3e6 DIFF: https://github.com/llvm/llvm-project/commit/a31a61dafeaa9110687110fc127ea6f7c91dd3e6.diff LOG: [clangd][Hover] Handle uninstantiated templates Summary: Fixes https://github.com/clangd/clangd/issues/263 Reviewers: hokein, sammccall Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D73344 Added: Modified: clang-tools-extra/clangd/Hover.cpp clang-tools-extra/clangd/unittests/HoverTests.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 26b6cf43109e..834c9d041872 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -26,6 +26,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/Type.h" +#include "clang/Basic/Specifiers.h" #include "clang/Index/IndexSymbol.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" @@ -205,15 +206,23 @@ const FunctionDecl *getUnderlyingFunction(const Decl *D) { // Returns the decl that should be used for querying comments, either from index // or AST. const NamedDecl *getDeclForComment(const NamedDecl *D) { - if (auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) - if (!CTSD->isExplicitInstantiationOrSpecialization()) - return CTSD->getTemplateInstantiationPattern(); - if (auto *VTSD = llvm::dyn_cast<VarTemplateSpecializationDecl>(D)) - if (!VTSD->isExplicitInstantiationOrSpecialization()) - return VTSD->getTemplateInstantiationPattern(); - if (auto *FD = D->getAsFunction()) - if (FD->isTemplateInstantiation()) - return FD->getTemplateInstantiationPattern(); + if (const auto *TSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) { + // Template may not be instantiated e.g. if the type didn't need to be + // complete; fallback to primary template. + if (TSD->getTemplateSpecializationKind() == TSK_Undeclared) + return TSD->getSpecializedTemplate(); + if (const auto *TIP = TSD->getTemplateInstantiationPattern()) + return TIP; + } + if (const auto *TSD = llvm::dyn_cast<VarTemplateSpecializationDecl>(D)) { + if (TSD->getTemplateSpecializationKind() == TSK_Undeclared) + return TSD->getSpecializedTemplate(); + if (const auto *TIP = TSD->getTemplateInstantiationPattern()) + return TIP; + } + if (const auto *FD = D->getAsFunction()) + if (const auto *TIP = FD->getTemplateInstantiationPattern()) + return TIP; return D; } diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index bb14ede135ca..758c64208fd8 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -554,6 +554,25 @@ class Foo {})cpp"; HI.Name = "Foo<X>"; HI.Kind = index::SymbolKind::Class; }}, + {// Falls back to primary template, when the type is not instantiated. + R"cpp( + // comment from primary + template <typename T> class Foo {}; + // comment from specialization + template <typename T> class Foo<T*> {}; + void foo() { + [[Fo^o]]<int*> *x = nullptr; + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "Foo<int *>"; + HI.Kind = index::SymbolKind::Class; + HI.NamespaceScope = ""; + HI.Definition = "template <> class Foo<int *>"; + // FIXME: Maybe force instantiation to make use of real template + // pattern. + HI.Documentation = "comment from primary"; + }}, }; for (const auto &Case : Cases) { SCOPED_TRACE(Case.Code); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits