Skip to content

Commit

Permalink
[clangd] Fix the incomplete template specialization in findTarget.
Browse files Browse the repository at this point in the history
Summary:
FindTarget doesn't report the TemplatePattern for incomplete
specialization.

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D74900
  • Loading branch information
hokein committed Feb 21, 2020
1 parent 97f1160 commit e326f52
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 1 deletion.
10 changes: 9 additions & 1 deletion clang-tools-extra/clangd/FindTarget.cpp
Expand Up @@ -31,6 +31,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
Expand Down Expand Up @@ -139,7 +140,14 @@ const Type *getPointeeType(const Type *T) {

const NamedDecl *getTemplatePattern(const NamedDecl *D) {
if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {
return CRD->getTemplateInstantiationPattern();
if (const auto *Result = CRD->getTemplateInstantiationPattern())
return Result;
// getTemplateInstantiationPattern returns null if the Specialization is
// incomplete (e.g. the type didn't need to be complete), fall back to the
// primary template.
if (CRD->getTemplateSpecializationKind() == TSK_Undeclared)
if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(CRD))
return Spec->getSpecializedTemplate()->getTemplatedDecl();
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
return FD->getTemplateInstantiationPattern();
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
Expand Down
10 changes: 10 additions & 0 deletions clang-tools-extra/clangd/unittests/FindTargetTests.cpp
Expand Up @@ -309,6 +309,16 @@ TEST_F(TargetDeclTest, ClassTemplate) {
{"template<> class Foo<42>", Rel::TemplateInstantiation},
{"class Foo", Rel::TemplatePattern});

Code = R"cpp(
template<typename T> class Foo {};
// The "Foo<int>" SpecializationDecl is incomplete, there is no
// instantiation happening.
void func([[Foo<int>]] *);
)cpp";
EXPECT_DECLS("TemplateSpecializationTypeLoc",
{"class Foo", Rel::TemplatePattern},
{"template<> class Foo<int>", Rel::TemplateInstantiation});

Code = R"cpp(
// Explicit specialization.
template<int x> class Foo{};
Expand Down
6 changes: 6 additions & 0 deletions clang-tools-extra/clangd/unittests/XRefsTests.cpp
Expand Up @@ -954,6 +954,12 @@ TEST(FindReferences, WithinAST) {
class [[Fo^o]] {};
void func([[Foo]]<int>);
)cpp",

R"cpp(
template <typename T>
class [[Foo]] {};
void func([[Fo^o]]<int>);
)cpp",
};
for (const char *Test : Tests) {
Annotations T(Test);
Expand Down

0 comments on commit e326f52

Please sign in to comment.