forked from OSchip/llvm-project
[clangd] Handle the new Using TemplateName.
Add supports in FindTarget and IncludeCleaner. This would improve AST-based features on a tempalte which is found via a using declaration. For example, go-to-def on `vect^or<int> v;` gives us the location of `using std::vector`, which was not previously. Base on https://reviews.llvm.org/D123127 Differential Revision: https://reviews.llvm.org/D123212
This commit is contained in:
parent
37b1515b0a
commit
95f0f69441
|
@ -384,11 +384,14 @@ public:
|
|||
}
|
||||
void VisitDeducedTemplateSpecializationType(
|
||||
const DeducedTemplateSpecializationType *DTST) {
|
||||
if (const auto *USD = DTST->getTemplateName().getAsUsingShadowDecl())
|
||||
Outer.add(USD, Flags);
|
||||
|
||||
// FIXME: This is a workaround for https://llvm.org/PR42914,
|
||||
// which is causing DTST->getDeducedType() to be empty. We
|
||||
// fall back to the template pattern and miss the instantiation
|
||||
// even when it's known in principle. Once that bug is fixed,
|
||||
// this method can be removed (the existing handling in
|
||||
// the following code can be removed (the existing handling in
|
||||
// VisitDeducedType() is sufficient).
|
||||
if (auto *TD = DTST->getTemplateName().getAsTemplateDecl())
|
||||
Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern);
|
||||
|
@ -419,6 +422,9 @@ public:
|
|||
VisitTemplateSpecializationType(const TemplateSpecializationType *TST) {
|
||||
// Have to handle these case-by-case.
|
||||
|
||||
if (const auto *UTN = TST->getTemplateName().getAsUsingShadowDecl())
|
||||
Outer.add(UTN, Flags);
|
||||
|
||||
// templated type aliases: there's no specialized/instantiated using
|
||||
// decl to point to. So try to find a decl for the underlying type
|
||||
// (after substitution), and failing that point to the (templated) using
|
||||
|
@ -508,6 +514,9 @@ public:
|
|||
Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) {
|
||||
report(TD, Flags);
|
||||
}
|
||||
if (const auto *USD =
|
||||
Arg.getAsTemplateOrTemplatePattern().getAsUsingShadowDecl())
|
||||
add(USD, Flags);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -79,11 +79,29 @@ public:
|
|||
}
|
||||
|
||||
bool VisitTemplateSpecializationType(TemplateSpecializationType *TST) {
|
||||
add(TST->getTemplateName().getAsTemplateDecl()); // Primary template.
|
||||
// Using templateName case is handled by the override TraverseTemplateName.
|
||||
if (TST->getTemplateName().getKind() == TemplateName::UsingTemplate)
|
||||
return true;
|
||||
add(TST->getAsCXXRecordDecl()); // Specialization
|
||||
return true;
|
||||
}
|
||||
|
||||
// There is no VisitTemplateName in RAV, thus we override the Traverse version
|
||||
// to handle the Using TemplateName case.
|
||||
bool TraverseTemplateName(TemplateName TN) {
|
||||
VisitTemplateName(TN);
|
||||
return Base::TraverseTemplateName(TN);
|
||||
}
|
||||
// A pseudo VisitTemplateName, dispatched by the above TraverseTemplateName!
|
||||
bool VisitTemplateName(TemplateName TN) {
|
||||
if (const auto *USD = TN.getAsUsingShadowDecl()) {
|
||||
add(USD);
|
||||
return true;
|
||||
}
|
||||
add(TN.getAsTemplateDecl()); // Primary template.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitUsingType(UsingType *UT) {
|
||||
add(UT->getFoundDecl());
|
||||
return true;
|
||||
|
|
|
@ -229,6 +229,45 @@ TEST_F(TargetDeclTest, UsingDecl) {
|
|||
)cpp";
|
||||
EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base<T>::waldo", Rel::Alias},
|
||||
{"void waldo()"});
|
||||
|
||||
Code = R"cpp(
|
||||
namespace ns {
|
||||
template<typename T> class S {};
|
||||
}
|
||||
|
||||
using ns::S;
|
||||
|
||||
template<typename T>
|
||||
using A = [[S]]<T>;
|
||||
)cpp";
|
||||
EXPECT_DECLS("TemplateSpecializationTypeLoc", {"using ns::S", Rel::Alias},
|
||||
{"template <typename T> class S"},
|
||||
{"class S", Rel::TemplatePattern});
|
||||
|
||||
Code = R"cpp(
|
||||
namespace ns {
|
||||
template<typename T> class S {};
|
||||
}
|
||||
|
||||
using ns::S;
|
||||
template <template <typename> class T> class X {};
|
||||
using B = X<[[S]]>;
|
||||
)cpp";
|
||||
EXPECT_DECLS("TemplateArgumentLoc", {"using ns::S", Rel::Alias},
|
||||
{"template <typename T> class S"});
|
||||
|
||||
Code = R"cpp(
|
||||
namespace ns {
|
||||
template<typename T> class S { public: S(T); };
|
||||
}
|
||||
|
||||
using ns::S;
|
||||
[[S]] s(123);
|
||||
)cpp";
|
||||
Flags.push_back("-std=c++17"); // For CTAD feature.
|
||||
EXPECT_DECLS("DeducedTemplateSpecializationTypeLoc",
|
||||
{"using ns::S", Rel::Alias}, {"template <typename T> class S"},
|
||||
{"class S", Rel::TemplatePattern});
|
||||
}
|
||||
|
||||
TEST_F(TargetDeclTest, BaseSpecifier) {
|
||||
|
|
|
@ -79,9 +79,22 @@ TEST(IncludeCleaner, ReferencedLocations) {
|
|||
"using namespace ns;",
|
||||
},
|
||||
{
|
||||
// Refs from UsingTypeLoc and implicit constructor!
|
||||
"struct ^A {}; using B = A; using ^C = B;",
|
||||
"C a;",
|
||||
},
|
||||
{"namespace ns { template<typename T> class A {}; } using ns::^A;",
|
||||
"A<int>* a;"},
|
||||
{"namespace ns { template<typename T> class A {}; } using ns::^A;",
|
||||
R"cpp(
|
||||
template <template <typename> class T> class X {};
|
||||
X<A> x;
|
||||
)cpp"},
|
||||
{R"cpp(
|
||||
namespace ns { template<typename T> struct ^A { ^A(T); }; }
|
||||
using ns::^A;
|
||||
)cpp",
|
||||
"A CATD(123);"},
|
||||
{
|
||||
"typedef bool ^Y; template <typename T> struct ^X {};",
|
||||
"X<Y> x;",
|
||||
|
@ -227,6 +240,7 @@ TEST(IncludeCleaner, ReferencedLocations) {
|
|||
TU.Code = T.MainCode;
|
||||
Annotations Header(T.HeaderCode);
|
||||
TU.HeaderCode = Header.code().str();
|
||||
TU.ExtraArgs.push_back("-std=c++17");
|
||||
auto AST = TU.build();
|
||||
|
||||
std::vector<Position> Points;
|
||||
|
|
Loading…
Reference in New Issue