)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) {
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() {
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() {
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;
$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() {
$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>;
$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;
$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;
$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
$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();
}
}
)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;
$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*);
$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);
$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>
$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 {};
$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() {
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
};
}
)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;
$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;