forked from OSchip/llvm-project
[clangd] Find reference to template parameter in 'sizeof...' expression
Fixes https://github.com/clangd/clangd/issues/213. Reviewers: ilya-biryukov Reviewed By: ilya-biryukov Subscribers: MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D70740
This commit is contained in:
parent
19071173fc
commit
1a4ee4c88f
|
@ -197,6 +197,9 @@ public:
|
|||
for (auto *D : OE->decls())
|
||||
Outer.add(D, Flags);
|
||||
}
|
||||
void VisitSizeOfPackExpr(const SizeOfPackExpr *SE) {
|
||||
Outer.add(SE->getPack(), Flags);
|
||||
}
|
||||
void VisitCXXConstructExpr(const CXXConstructExpr *CCE) {
|
||||
Outer.add(CCE->getConstructor(), Flags);
|
||||
}
|
||||
|
@ -494,6 +497,13 @@ llvm::SmallVector<ReferenceLoc, 2> refInExpr(const Expr *E) {
|
|||
llvm::SmallVector<const NamedDecl *, 1>(
|
||||
E->decls().begin(), E->decls().end())});
|
||||
}
|
||||
|
||||
void VisitSizeOfPackExpr(const SizeOfPackExpr *E) {
|
||||
Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
|
||||
E->getPackLoc(),
|
||||
/*IsDecl=*/false,
|
||||
{E->getPack()}});
|
||||
}
|
||||
};
|
||||
|
||||
Visitor V;
|
||||
|
|
|
@ -277,6 +277,15 @@ TEST_F(TargetDeclTest, Types) {
|
|||
)cpp";
|
||||
// FIXME: deduced type missing in AST. https://llvm.org/PR42914
|
||||
EXPECT_DECLS("AutoTypeLoc");
|
||||
|
||||
Code = R"cpp(
|
||||
template <typename... E>
|
||||
struct S {
|
||||
static const int size = sizeof...([[E]]);
|
||||
};
|
||||
)cpp";
|
||||
// FIXME: We don't do a good job printing TemplateTypeParmDecls, apparently!
|
||||
EXPECT_DECLS("SizeOfPackExpr", "");
|
||||
}
|
||||
|
||||
TEST_F(TargetDeclTest, ClassTemplate) {
|
||||
|
@ -593,28 +602,27 @@ protected:
|
|||
|
||||
TEST_F(FindExplicitReferencesTest, All) {
|
||||
std::pair</*Code*/ llvm::StringRef, /*References*/ llvm::StringRef> Cases[] =
|
||||
{
|
||||
// Simple expressions.
|
||||
{R"cpp(
|
||||
{// Simple expressions.
|
||||
{R"cpp(
|
||||
int global;
|
||||
int func();
|
||||
void foo(int param) {
|
||||
$0^global = $1^param + $2^func();
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {global}\n"
|
||||
"1: targets = {param}\n"
|
||||
"2: targets = {func}\n"},
|
||||
{R"cpp(
|
||||
"0: targets = {global}\n"
|
||||
"1: targets = {param}\n"
|
||||
"2: targets = {func}\n"},
|
||||
{R"cpp(
|
||||
struct X { int a; };
|
||||
void foo(X x) {
|
||||
$0^x.$1^a = 10;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {x}\n"
|
||||
"1: targets = {X::a}\n"},
|
||||
// Namespaces and aliases.
|
||||
{R"cpp(
|
||||
"0: targets = {x}\n"
|
||||
"1: targets = {X::a}\n"},
|
||||
// Namespaces and aliases.
|
||||
{R"cpp(
|
||||
namespace ns {}
|
||||
namespace alias = ns;
|
||||
void foo() {
|
||||
|
@ -622,19 +630,19 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
using namespace $1^alias;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {ns}\n"
|
||||
"1: targets = {alias}\n"},
|
||||
// Using declarations.
|
||||
{R"cpp(
|
||||
"0: targets = {ns}\n"
|
||||
"1: targets = {alias}\n"},
|
||||
// Using declarations.
|
||||
{R"cpp(
|
||||
namespace ns { int global; }
|
||||
void foo() {
|
||||
using $0^ns::$1^global;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {ns}\n"
|
||||
"1: targets = {ns::global}, qualifier = 'ns::'\n"},
|
||||
// Simple types.
|
||||
{R"cpp(
|
||||
"0: targets = {ns}\n"
|
||||
"1: targets = {ns::global}, qualifier = 'ns::'\n"},
|
||||
// Simple types.
|
||||
{R"cpp(
|
||||
struct Struct { int a; };
|
||||
using Typedef = int;
|
||||
void foo() {
|
||||
|
@ -643,13 +651,13 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
static_cast<$4^Struct*>(0);
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {Struct}\n"
|
||||
"1: targets = {x}, decl\n"
|
||||
"2: targets = {Typedef}\n"
|
||||
"3: targets = {y}, decl\n"
|
||||
"4: targets = {Struct}\n"},
|
||||
// Name qualifiers.
|
||||
{R"cpp(
|
||||
"0: targets = {Struct}\n"
|
||||
"1: targets = {x}, decl\n"
|
||||
"2: targets = {Typedef}\n"
|
||||
"3: targets = {y}, decl\n"
|
||||
"4: targets = {Struct}\n"},
|
||||
// Name qualifiers.
|
||||
{R"cpp(
|
||||
namespace a { namespace b { struct S { typedef int type; }; } }
|
||||
void foo() {
|
||||
$0^a::$1^b::$2^S $3^x;
|
||||
|
@ -657,17 +665,17 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$6^S::$7^type $8^y;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {a}\n"
|
||||
"1: targets = {a::b}, qualifier = 'a::'\n"
|
||||
"2: targets = {a::b::S}, qualifier = 'a::b::'\n"
|
||||
"3: targets = {x}, decl\n"
|
||||
"4: targets = {a}\n"
|
||||
"5: targets = {a::b}, qualifier = 'a::'\n"
|
||||
"6: targets = {a::b::S}\n"
|
||||
"7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
|
||||
"8: targets = {y}, decl\n"},
|
||||
// Simple templates.
|
||||
{R"cpp(
|
||||
"0: targets = {a}\n"
|
||||
"1: targets = {a::b}, qualifier = 'a::'\n"
|
||||
"2: targets = {a::b::S}, qualifier = 'a::b::'\n"
|
||||
"3: targets = {x}, decl\n"
|
||||
"4: targets = {a}\n"
|
||||
"5: targets = {a::b}, qualifier = 'a::'\n"
|
||||
"6: targets = {a::b::S}\n"
|
||||
"7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
|
||||
"8: targets = {y}, decl\n"},
|
||||
// Simple templates.
|
||||
{R"cpp(
|
||||
template <class T> struct vector { using value_type = T; };
|
||||
template <> struct vector<bool> { using value_type = bool; };
|
||||
void foo() {
|
||||
|
@ -675,12 +683,12 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$2^vector<bool> $3^vb;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {vector<int>}\n"
|
||||
"1: targets = {vi}, decl\n"
|
||||
"2: targets = {vector<bool>}\n"
|
||||
"3: targets = {vb}, decl\n"},
|
||||
// Template type aliases.
|
||||
{R"cpp(
|
||||
"0: targets = {vector<int>}\n"
|
||||
"1: targets = {vi}, decl\n"
|
||||
"2: targets = {vector<bool>}\n"
|
||||
"3: targets = {vb}, decl\n"},
|
||||
// Template type aliases.
|
||||
{R"cpp(
|
||||
template <class T> struct vector { using value_type = T; };
|
||||
template <> struct vector<bool> { using value_type = bool; };
|
||||
template <class T> using valias = vector<T>;
|
||||
|
@ -689,12 +697,12 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$2^valias<bool> $3^vb;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {valias}\n"
|
||||
"1: targets = {vi}, decl\n"
|
||||
"2: targets = {valias}\n"
|
||||
"3: targets = {vb}, decl\n"},
|
||||
// MemberExpr should know their using declaration.
|
||||
{R"cpp(
|
||||
"0: targets = {valias}\n"
|
||||
"1: targets = {vi}, decl\n"
|
||||
"2: targets = {valias}\n"
|
||||
"3: targets = {vb}, decl\n"},
|
||||
// MemberExpr should know their using declaration.
|
||||
{R"cpp(
|
||||
struct X { void func(int); }
|
||||
struct Y : X {
|
||||
using X::func;
|
||||
|
@ -703,10 +711,10 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$0^y.$1^func(1);
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {y}\n"
|
||||
"1: targets = {Y::func}\n"},
|
||||
// DeclRefExpr should know their using declaration.
|
||||
{R"cpp(
|
||||
"0: targets = {y}\n"
|
||||
"1: targets = {Y::func}\n"},
|
||||
// DeclRefExpr should know their using declaration.
|
||||
{R"cpp(
|
||||
namespace ns { void bar(int); }
|
||||
using ns::bar;
|
||||
|
||||
|
@ -714,9 +722,9 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$0^bar(10);
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {bar}\n"},
|
||||
// References from a macro.
|
||||
{R"cpp(
|
||||
"0: targets = {bar}\n"},
|
||||
// References from a macro.
|
||||
{R"cpp(
|
||||
#define FOO a
|
||||
#define BAR b
|
||||
|
||||
|
@ -724,10 +732,10 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$0^FOO+$1^BAR;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {a}\n"
|
||||
"1: targets = {b}\n"},
|
||||
// No references from implicit nodes.
|
||||
{R"cpp(
|
||||
"0: targets = {a}\n"
|
||||
"1: targets = {b}\n"},
|
||||
// No references from implicit nodes.
|
||||
{R"cpp(
|
||||
struct vector {
|
||||
int *begin();
|
||||
int *end();
|
||||
|
@ -739,11 +747,11 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
}
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {x}, decl\n"
|
||||
"1: targets = {vector}\n"
|
||||
"2: targets = {x}\n"},
|
||||
// Handle UnresolvedLookupExpr.
|
||||
{R"cpp(
|
||||
"0: targets = {x}, decl\n"
|
||||
"1: targets = {vector}\n"
|
||||
"2: targets = {x}\n"},
|
||||
// Handle UnresolvedLookupExpr.
|
||||
{R"cpp(
|
||||
namespace ns1 { void func(char*); }
|
||||
namespace ns2 { void func(int*); }
|
||||
using namespace ns1;
|
||||
|
@ -754,10 +762,10 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$0^func($1^t);
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {ns1::func, ns2::func}\n"
|
||||
"1: targets = {t}\n"},
|
||||
// Handle UnresolvedMemberExpr.
|
||||
{R"cpp(
|
||||
"0: targets = {ns1::func, ns2::func}\n"
|
||||
"1: targets = {t}\n"},
|
||||
// Handle UnresolvedMemberExpr.
|
||||
{R"cpp(
|
||||
struct X {
|
||||
void func(char*);
|
||||
void func(int*);
|
||||
|
@ -768,11 +776,11 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$0^x.$1^func($2^t);
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {x}\n"
|
||||
"1: targets = {X::func, X::func}\n"
|
||||
"2: targets = {t}\n"},
|
||||
// Type template parameters.
|
||||
{R"cpp(
|
||||
"0: targets = {x}\n"
|
||||
"1: targets = {X::func, X::func}\n"
|
||||
"2: targets = {t}\n"},
|
||||
// Type template parameters.
|
||||
{R"cpp(
|
||||
template <class T>
|
||||
void foo() {
|
||||
static_cast<$0^T>(0);
|
||||
|
@ -780,21 +788,21 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$2^T $3^t;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {T}\n"
|
||||
"1: targets = {T}\n"
|
||||
"2: targets = {T}\n"
|
||||
"3: targets = {t}, decl\n"},
|
||||
// Non-type template parameters.
|
||||
{R"cpp(
|
||||
"0: targets = {T}\n"
|
||||
"1: targets = {T}\n"
|
||||
"2: targets = {T}\n"
|
||||
"3: targets = {t}, decl\n"},
|
||||
// Non-type template parameters.
|
||||
{R"cpp(
|
||||
template <int I>
|
||||
void foo() {
|
||||
int $0^x = $1^I;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {x}, decl\n"
|
||||
"1: targets = {I}\n"},
|
||||
// Template template parameters.
|
||||
{R"cpp(
|
||||
"0: targets = {x}, decl\n"
|
||||
"1: targets = {I}\n"},
|
||||
// Template template parameters.
|
||||
{R"cpp(
|
||||
template <class T> struct vector {};
|
||||
|
||||
template <template<class> class TT, template<class> class ...TP>
|
||||
|
@ -805,16 +813,16 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$6^foo<$7^TP...>();
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {TT}\n"
|
||||
"1: targets = {x}, decl\n"
|
||||
"2: targets = {foo}\n"
|
||||
"3: targets = {TT}\n"
|
||||
"4: targets = {foo}\n"
|
||||
"5: targets = {vector}\n"
|
||||
"6: targets = {foo}\n"
|
||||
"7: targets = {TP}\n"},
|
||||
// Non-type template parameters with declarations.
|
||||
{R"cpp(
|
||||
"0: targets = {TT}\n"
|
||||
"1: targets = {x}, decl\n"
|
||||
"2: targets = {foo}\n"
|
||||
"3: targets = {TT}\n"
|
||||
"4: targets = {foo}\n"
|
||||
"5: targets = {vector}\n"
|
||||
"6: targets = {foo}\n"
|
||||
"7: targets = {TP}\n"},
|
||||
// Non-type template parameters with declarations.
|
||||
{R"cpp(
|
||||
int func();
|
||||
template <int(*)()> struct wrapper {};
|
||||
|
||||
|
@ -824,12 +832,12 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$3^FuncParam();
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {wrapper<&func>}\n"
|
||||
"1: targets = {func}\n"
|
||||
"2: targets = {w}, decl\n"
|
||||
"3: targets = {FuncParam}\n"},
|
||||
// declaration references.
|
||||
{R"cpp(
|
||||
"0: targets = {wrapper<&func>}\n"
|
||||
"1: targets = {func}\n"
|
||||
"2: targets = {w}, decl\n"
|
||||
"3: targets = {FuncParam}\n"},
|
||||
// declaration references.
|
||||
{R"cpp(
|
||||
namespace ns {}
|
||||
class S {};
|
||||
void foo() {
|
||||
|
@ -841,19 +849,19 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
namespace $9^NS = $10^ns;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {Foo}, decl\n"
|
||||
"1: targets = {foo()::Foo::Foo}, decl\n"
|
||||
"2: targets = {Foo}\n"
|
||||
"3: targets = {foo()::Foo::field}, decl\n"
|
||||
"4: targets = {Var}, decl\n"
|
||||
"5: targets = {E}, decl\n"
|
||||
"6: targets = {foo()::ABC}, decl\n"
|
||||
"7: targets = {INT}, decl\n"
|
||||
"8: targets = {INT2}, decl\n"
|
||||
"9: targets = {NS}, decl\n"
|
||||
"10: targets = {ns}\n"},
|
||||
// cxx constructor initializer.
|
||||
{R"cpp(
|
||||
"0: targets = {Foo}, decl\n"
|
||||
"1: targets = {foo()::Foo::Foo}, decl\n"
|
||||
"2: targets = {Foo}\n"
|
||||
"3: targets = {foo()::Foo::field}, decl\n"
|
||||
"4: targets = {Var}, decl\n"
|
||||
"5: targets = {E}, decl\n"
|
||||
"6: targets = {foo()::ABC}, decl\n"
|
||||
"7: targets = {INT}, decl\n"
|
||||
"8: targets = {INT2}, decl\n"
|
||||
"9: targets = {NS}, decl\n"
|
||||
"10: targets = {ns}\n"},
|
||||
// cxx constructor initializer.
|
||||
{R"cpp(
|
||||
class Base {};
|
||||
void foo() {
|
||||
// member initializer
|
||||
|
@ -873,34 +881,34 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
};
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {X}, decl\n"
|
||||
"1: targets = {foo()::X::abc}, decl\n"
|
||||
"2: targets = {foo()::X::X}, decl\n"
|
||||
"3: targets = {foo()::X::abc}\n"
|
||||
"4: targets = {Derived}, decl\n"
|
||||
"5: targets = {Base}\n"
|
||||
"6: targets = {Base}\n"
|
||||
"7: targets = {foo()::Derived::B}, decl\n"
|
||||
"8: targets = {foo()::Derived::Derived}, decl\n"
|
||||
"9: targets = {Base}\n"
|
||||
"10: targets = {Foo}, decl\n"
|
||||
"11: targets = {foo()::Foo::Foo}, decl\n"
|
||||
"12: targets = {foo()::Foo::Foo}, decl\n"
|
||||
"13: targets = {Foo}\n"},
|
||||
// Anonymous entities should not be reported.
|
||||
{
|
||||
R"cpp(
|
||||
"0: targets = {X}, decl\n"
|
||||
"1: targets = {foo()::X::abc}, decl\n"
|
||||
"2: targets = {foo()::X::X}, decl\n"
|
||||
"3: targets = {foo()::X::abc}\n"
|
||||
"4: targets = {Derived}, decl\n"
|
||||
"5: targets = {Base}\n"
|
||||
"6: targets = {Base}\n"
|
||||
"7: targets = {foo()::Derived::B}, decl\n"
|
||||
"8: targets = {foo()::Derived::Derived}, decl\n"
|
||||
"9: targets = {Base}\n"
|
||||
"10: targets = {Foo}, decl\n"
|
||||
"11: targets = {foo()::Foo::Foo}, decl\n"
|
||||
"12: targets = {foo()::Foo::Foo}, decl\n"
|
||||
"13: targets = {Foo}\n"},
|
||||
// Anonymous entities should not be reported.
|
||||
{
|
||||
R"cpp(
|
||||
void foo() {
|
||||
class {} $0^x;
|
||||
int (*$1^fptr)(int $2^a, int) = nullptr;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {x}, decl\n"
|
||||
"1: targets = {fptr}, decl\n"
|
||||
"2: targets = {a}, decl\n"},
|
||||
// Namespace aliases should be handled properly.
|
||||
{
|
||||
R"cpp(
|
||||
"0: targets = {x}, decl\n"
|
||||
"1: targets = {fptr}, decl\n"
|
||||
"2: targets = {a}, decl\n"},
|
||||
// Namespace aliases should be handled properly.
|
||||
{
|
||||
R"cpp(
|
||||
namespace ns { struct Type {} }
|
||||
namespace alias = ns;
|
||||
namespace rec_alias = alias;
|
||||
|
@ -911,16 +919,25 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
$6^rec_alias::$7^Type $8^c;
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {ns}\n"
|
||||
"1: targets = {ns::Type}, qualifier = 'ns::'\n"
|
||||
"2: targets = {a}, decl\n"
|
||||
"3: targets = {alias}\n"
|
||||
"4: targets = {ns::Type}, qualifier = 'alias::'\n"
|
||||
"5: targets = {b}, decl\n"
|
||||
"6: targets = {rec_alias}\n"
|
||||
"7: targets = {ns::Type}, qualifier = 'rec_alias::'\n"
|
||||
"8: targets = {c}, decl\n"},
|
||||
};
|
||||
"0: targets = {ns}\n"
|
||||
"1: targets = {ns::Type}, qualifier = 'ns::'\n"
|
||||
"2: targets = {a}, decl\n"
|
||||
"3: targets = {alias}\n"
|
||||
"4: targets = {ns::Type}, qualifier = 'alias::'\n"
|
||||
"5: targets = {b}, decl\n"
|
||||
"6: targets = {rec_alias}\n"
|
||||
"7: targets = {ns::Type}, qualifier = 'rec_alias::'\n"
|
||||
"8: targets = {c}, decl\n"},
|
||||
// Handle SizeOfPackExpr.
|
||||
{
|
||||
R"cpp(
|
||||
template <typename... E>
|
||||
void foo() {
|
||||
constexpr int $0^size = sizeof...($1^E);
|
||||
};
|
||||
)cpp",
|
||||
"0: targets = {size}, decl\n"
|
||||
"1: targets = {E}\n"}};
|
||||
|
||||
for (const auto &C : Cases) {
|
||||
llvm::StringRef ExpectedCode = C.first;
|
||||
|
|
|
@ -625,6 +625,13 @@ $InactiveCode[[]] int Inactive3;
|
|||
$InactiveCode[[]] #else
|
||||
int $Variable[[Active2]];
|
||||
#endif
|
||||
)cpp",
|
||||
// Argument to 'sizeof...'
|
||||
R"cpp(
|
||||
template <typename... $TemplateParameter[[Elements]]>
|
||||
struct $Class[[TupleSize]] {
|
||||
static const int $StaticField[[size]] = sizeof...($TemplateParameter[[Elements]]);
|
||||
};
|
||||
)cpp"};
|
||||
for (const auto &TestCase : TestCases) {
|
||||
checkHighlightings(TestCase);
|
||||
|
|
Loading…
Reference in New Issue