Add support for polymorphic matchers. Use runtime type checking to determine the right polymorphic overload to use.
llvm-svn: 184558
diff --git a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
index fd6eaef..357a371 100644
--- a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -38,25 +38,23 @@
template <class T>
Matcher<T> constructMatcher(StringRef MatcherName, Diagnostics *Error) {
- OwningPtr<DynTypedMatcher> Out(
- Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error));
- return Matcher<T>::constructFrom(*Out);
+ return Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error)
+ .getTypedMatcher<T>();
}
template <class T>
Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
Diagnostics *Error) {
- OwningPtr<DynTypedMatcher> Out(Registry::constructMatcher(
- MatcherName, SourceRange(), Args(Arg1), Error));
- return Matcher<T>::constructFrom(*Out);
+ return Registry::constructMatcher(MatcherName, SourceRange(), Args(Arg1),
+ Error).getTypedMatcher<T>();
}
template <class T>
Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
const VariantValue &Arg2, Diagnostics *Error) {
- OwningPtr<DynTypedMatcher> Out(Registry::constructMatcher(
- MatcherName, SourceRange(), Args(Arg1, Arg2), Error));
- return Matcher<T>::constructFrom(*Out);
+ return Registry::constructMatcher(MatcherName, SourceRange(),
+ Args(Arg1, Arg2), Error)
+ .getTypedMatcher<T>();
}
};
@@ -115,34 +113,57 @@
EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
}
+TEST_F(RegistryTest, PolymorphicMatchers) {
+ const MatcherList IsDefinition =
+ Registry::constructMatcher("isDefinition", SourceRange(), Args(), NULL);
+ Matcher<Decl> Var = constructMatcher<Decl>("varDecl", IsDefinition, NULL);
+ Matcher<Decl> Class =
+ constructMatcher<Decl>("recordDecl", IsDefinition, NULL);
+ Matcher<Decl> Func =
+ constructMatcher<Decl>("functionDecl", IsDefinition, NULL);
+ EXPECT_TRUE(matches("int a;", Var));
+ EXPECT_FALSE(matches("extern int a;", Var));
+ EXPECT_TRUE(matches("class A {};", Class));
+ EXPECT_FALSE(matches("class A;", Class));
+ EXPECT_TRUE(matches("void f(){};", Func));
+ EXPECT_FALSE(matches("void f();", Func));
+
+ Matcher<Decl> Anything = constructMatcher<Decl>("anything", NULL);
+ Matcher<Decl> RecordDecl =
+ constructMatcher<Decl>("recordDecl", Anything, NULL);
+
+ EXPECT_TRUE(matches("int a;", Anything));
+ EXPECT_TRUE(matches("class A {};", Anything));
+ EXPECT_TRUE(matches("void f(){};", Anything));
+ EXPECT_FALSE(matches("int a;", RecordDecl));
+ EXPECT_TRUE(matches("class A {};", RecordDecl));
+ EXPECT_FALSE(matches("void f(){};", RecordDecl));
+}
+
TEST_F(RegistryTest, Errors) {
// Incorrect argument count.
OwningPtr<Diagnostics> Error(new Diagnostics());
- EXPECT_TRUE(NULL ==
- Registry::constructMatcher("hasInitializer", SourceRange(),
- Args(), Error.get()));
+ EXPECT_TRUE(Registry::constructMatcher("hasInitializer", SourceRange(),
+ Args(), Error.get()).empty());
EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
Error->ToString());
Error.reset(new Diagnostics());
- EXPECT_TRUE(NULL ==
- Registry::constructMatcher("isArrow", SourceRange(),
- Args(std::string()), Error.get()));
+ EXPECT_TRUE(Registry::constructMatcher(
+ "isArrow", SourceRange(), Args(std::string()), Error.get()).empty());
EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
Error->ToString());
// Bad argument type
Error.reset(new Diagnostics());
- EXPECT_TRUE(NULL ==
- Registry::constructMatcher("ofClass", SourceRange(),
- Args(std::string()), Error.get()));
+ EXPECT_TRUE(Registry::constructMatcher(
+ "ofClass", SourceRange(), Args(std::string()), Error.get()).empty());
EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
"(Actual = String)",
Error->ToString());
Error.reset(new Diagnostics());
- EXPECT_TRUE(NULL ==
- Registry::constructMatcher(
- "recordDecl", SourceRange(),
- Args(recordDecl(), parameterCountIs(3)), Error.get()));
+ EXPECT_TRUE(Registry::constructMatcher(
+ "recordDecl", SourceRange(), Args(recordDecl(), parameterCountIs(3)),
+ Error.get()).empty());
EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
"(Actual = Matcher<FunctionDecl>)",
Error->ToString());