mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-12 09:41:26 +00:00
AST Matchers: introduce functionTemplate(), classTemplate() and
isExplicitTemplateSpecialization() matchers which do what their name says. llvm-svn: 162115
This commit is contained in:
parent
34bc34ecae
commit
d394c8a83e
@ -164,6 +164,14 @@ const internal::VariadicDynCastAllOfMatcher<
|
||||
Decl,
|
||||
CXXRecordDecl> record;
|
||||
|
||||
/// \brief Matches C++ class template declarations.
|
||||
///
|
||||
/// Example matches Z
|
||||
/// template<class T> class Z {};
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Decl,
|
||||
ClassTemplateDecl> classTemplate;
|
||||
|
||||
/// \brief Matches C++ class template specializations.
|
||||
///
|
||||
/// Given
|
||||
@ -385,6 +393,13 @@ const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> field;
|
||||
/// void f();
|
||||
const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> function;
|
||||
|
||||
/// \brief Matches C++ function template declarations.
|
||||
///
|
||||
/// Example matches f
|
||||
/// template<class T> void f(T t) {}
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Decl,
|
||||
FunctionTemplateDecl> functionTemplate;
|
||||
|
||||
/// \brief Matches statements.
|
||||
///
|
||||
@ -1941,6 +1956,21 @@ isTemplateInstantiation() {
|
||||
internal::IsTemplateInstantiationMatcher>();
|
||||
}
|
||||
|
||||
/// \brief Matches explicit template specializations of function, class, or
|
||||
/// static member variable template instantiations.
|
||||
///
|
||||
/// Given
|
||||
/// template<typename T> void A(T t) { }
|
||||
/// template<> void A(int N) { }
|
||||
/// function(isExplicitSpecialization())
|
||||
/// matches the specialization A<int>().
|
||||
inline internal::PolymorphicMatcherWithParam0<
|
||||
internal::IsExplicitTemplateSpecializationMatcher>
|
||||
isExplicitTemplateSpecialization() {
|
||||
return internal::PolymorphicMatcherWithParam0<
|
||||
internal::IsExplicitTemplateSpecializationMatcher>();
|
||||
}
|
||||
|
||||
} // end namespace ast_matchers
|
||||
} // end namespace clang
|
||||
|
||||
|
@ -858,6 +858,23 @@ class IsTemplateInstantiationMatcher : public MatcherInterface<T> {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Matches on explicit template specializations for FunctionDecl,
|
||||
/// VarDecl or CXXRecordDecl nodes.
|
||||
template <typename T>
|
||||
class IsExplicitTemplateSpecializationMatcher : public MatcherInterface<T> {
|
||||
TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, T>::value) ||
|
||||
(llvm::is_base_of<VarDecl, T>::value) ||
|
||||
(llvm::is_base_of<CXXRecordDecl, T>::value),
|
||||
requires_getTemplateSpecializationKind_method);
|
||||
public:
|
||||
virtual bool matches(const T& Node,
|
||||
ASTMatchFinder* Finder,
|
||||
BoundNodesTreeBuilder* Builder) const {
|
||||
return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class IsArrowMatcher : public SingleNodeMatcherInterface<MemberExpr> {
|
||||
public:
|
||||
virtual bool matchesNode(const MemberExpr &Node) const {
|
||||
|
@ -292,6 +292,32 @@ TEST(DeclarationMatcher, ClassIsDerived) {
|
||||
record(isDerivedFrom(record(hasName("X")).bind("test")))));
|
||||
}
|
||||
|
||||
TEST(ClassTemplate, DoesNotMatchClass) {
|
||||
DeclarationMatcher ClassX = classTemplate(hasName("X"));
|
||||
EXPECT_TRUE(notMatches("class X;", ClassX));
|
||||
EXPECT_TRUE(notMatches("class X {};", ClassX));
|
||||
}
|
||||
|
||||
TEST(ClassTemplate, MatchesClassTemplate) {
|
||||
DeclarationMatcher ClassX = classTemplate(hasName("X"));
|
||||
EXPECT_TRUE(matches("template<typename T> class X {};", ClassX));
|
||||
EXPECT_TRUE(matches("class Z { template<class T> class X {}; };", ClassX));
|
||||
}
|
||||
|
||||
TEST(ClassTemplate, DoesNotMatchClassTemplateExplicitSpecialization) {
|
||||
EXPECT_TRUE(notMatches("template<typename T> class X { };"
|
||||
"template<> class X<int> { int a; };",
|
||||
classTemplate(hasName("X"),
|
||||
hasDescendant(field(hasName("a"))))));
|
||||
}
|
||||
|
||||
TEST(ClassTemplate, DoesNotMatchClassTemplatePartialSpecialization) {
|
||||
EXPECT_TRUE(notMatches("template<typename T, typename U> class X { };"
|
||||
"template<typename T> class X<T, int> { int a; };",
|
||||
classTemplate(hasName("X"),
|
||||
hasDescendant(field(hasName("a"))))));
|
||||
}
|
||||
|
||||
TEST(AllOf, AllOverloadsWork) {
|
||||
const char Program[] =
|
||||
"struct T { }; int f(int, T*); void g(int x) { T t; f(x, &t); }";
|
||||
@ -1017,6 +1043,27 @@ TEST(Function, MatchesFunctionDeclarations) {
|
||||
CallFunctionF));
|
||||
}
|
||||
|
||||
TEST(FunctionTemplate, MatchesFunctionTemplateDeclarations) {
|
||||
EXPECT_TRUE(
|
||||
matches("template <typename T> void f(T t) {}",
|
||||
functionTemplate(hasName("f"))));
|
||||
}
|
||||
|
||||
TEST(FunctionTemplate, DoesNotMatchFunctionDeclarations) {
|
||||
EXPECT_TRUE(
|
||||
notMatches("void f(double d); void f(int t) {}",
|
||||
functionTemplate(hasName("f"))));
|
||||
}
|
||||
|
||||
TEST(FunctionTemplate, DoesNotMatchFunctionTemplateSpecializations) {
|
||||
EXPECT_TRUE(
|
||||
notMatches("void g(); template <typename T> void f(T t) {}"
|
||||
"template <> void f(int t) { g(); }",
|
||||
functionTemplate(hasName("f"),
|
||||
hasDescendant(declarationReference(
|
||||
to(function(hasName("g"))))))));
|
||||
}
|
||||
|
||||
TEST(Matcher, Argument) {
|
||||
StatementMatcher CallArgumentY = expression(call(
|
||||
hasArgument(0, declarationReference(to(variable(hasName("y")))))));
|
||||
@ -2565,5 +2612,49 @@ TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) {
|
||||
record(isTemplateInstantiation())));
|
||||
}
|
||||
|
||||
TEST(IsExplicitTemplateSpecialization,
|
||||
DoesNotMatchPrimaryTemplate) {
|
||||
EXPECT_TRUE(notMatches(
|
||||
"template <typename T> class X {};",
|
||||
record(isExplicitTemplateSpecialization())));
|
||||
EXPECT_TRUE(notMatches(
|
||||
"template <typename T> void f(T t);",
|
||||
function(isExplicitTemplateSpecialization())));
|
||||
}
|
||||
|
||||
TEST(IsExplicitTemplateSpecialization,
|
||||
DoesNotMatchExplicitTemplateInstantiations) {
|
||||
EXPECT_TRUE(notMatches(
|
||||
"template <typename T> class X {};"
|
||||
"template class X<int>; extern template class X<long>;",
|
||||
record(isExplicitTemplateSpecialization())));
|
||||
EXPECT_TRUE(notMatches(
|
||||
"template <typename T> void f(T t) {}"
|
||||
"template void f(int t); extern template void f(long t);",
|
||||
function(isExplicitTemplateSpecialization())));
|
||||
}
|
||||
|
||||
TEST(IsExplicitTemplateSpecialization,
|
||||
DoesNotMatchImplicitTemplateInstantiations) {
|
||||
EXPECT_TRUE(notMatches(
|
||||
"template <typename T> class X {}; X<int> x;",
|
||||
record(isExplicitTemplateSpecialization())));
|
||||
EXPECT_TRUE(notMatches(
|
||||
"template <typename T> void f(T t); void g() { f(10); }",
|
||||
function(isExplicitTemplateSpecialization())));
|
||||
}
|
||||
|
||||
TEST(IsExplicitTemplateSpecialization,
|
||||
MatchesExplicitTemplateSpecializations) {
|
||||
EXPECT_TRUE(matches(
|
||||
"template <typename T> class X {};"
|
||||
"template<> class X<int> {};",
|
||||
record(isExplicitTemplateSpecialization())));
|
||||
EXPECT_TRUE(matches(
|
||||
"template <typename T> void f(T t) {}"
|
||||
"template<> void f(int t) {}",
|
||||
function(isExplicitTemplateSpecialization())));
|
||||
}
|
||||
|
||||
} // end namespace ast_matchers
|
||||
} // end namespace clang
|
||||
|
Loading…
Reference in New Issue
Block a user